이전에 실행된 SSH 명령의 PID 예측

이전에 실행된 SSH 명령의 PID 예측

이것은 가장 이상한 것입니다.

스크립트에서는 다음과 같이 SSH 터널을 시작합니다.

ssh -o StrictHostkeyChecking=no -fND 8080 foo@bar

그러면 ssh백그라운드로 들어가는 인스턴스가 시작되고 스크립트가 계속 실행됩니다. 다음으로 bash를 사용하여 PID를 저장합니다(나중에 종료할 수 있도록).$! 바꾸다. 작동하게 하려면 명령 자체가 백그라운드로 들어가더라도 명령 &에 추가합니다(그렇지 않으면 아무것도 포함하지 않습니다). 예를 들어 다음 스크립트는 다음과 같습니다.ssh$!

#!/bin/bash

ssh -o StrictHostkeyChecking=no -fND 8080 foo@bar &
echo $!
pgrep -f "ssh -o StrictHostkeyChecking=no -fND 8080 foo@bar"

산출

(some ssh output)
28062
28062

...예상대로 동일한 PID에 대해 두 번 발생합니다. 하지만 지금은 내가 처형할 때이 정확한 명령 순서터미널에서 PID 출력은 $!다음과 같습니다.잘못된(어떤 의미에서는 그렇죠.아니요인스턴스의 PID ssh). 터미널에서:

$ ssh -o StrictHostkeyChecking=no -fND 8080 foo@bar &
[1] 28178
(some ssh output)
$ echo $!
28178
$ pgrep -f "ssh -o StrictHostkeyChecking=no -fND 8080 foo@bar"
28181

항상 3자리 숫자가 차이나는 것은 아닙니다. 저도 1~2정도 차이가 나더군요. 그러나 예상한 대로 PID는 결코 동일하지 않으며, 스크립트에서 일련의 명령이 실행될 때에도 마찬가지입니다.

  1. 왜 이런 일이 발생하는지 설명할 수 있나요? 나는 이것이 실제로 다른 프로세스를 분기하는 초기 호출 때문일 수 있다고 생각했지만 ssh왜 스크립트 내부에서 작동합니까?

  2. $!이것은 또한 스크립트에서 sshPID를 얻기 위해 위에서 설명한 방법을 사용하는 것이 실제로 항상 작동할지 여부에 대한 의문을 갖게 합니다 (지금까지는 작동했지만). 이게 정말 믿을 만한 걸까요? pgrep사용하는 것보다 "깨끗하다" 고 생각합니다 ...

답변1

쉘의 $!변수는 쉘에 의해 시작된 프로세스의 pid만 알고 있습니다. 예상한 대로 호출은 자체 프로세스의 포크를 ssh사용하여 이루어 -f지므로 백그라운드로 이동할 수 있으므로 전체 프로세스 트리는 [1]과 같습니다.

shell
|
+--ssh<1> (pid is $!)
   |
   +--ssh<2> (pid is different)

ssh<1>호출 직후 종료되므로 의 값은 $!유용하지 않습니다. ssh<2>원격 통신과 터널 설정을 담당하며 PID를 안정적으로 얻는 유일한 방법은 [ pgrep2]에서 했던 것처럼 프로세스 테이블을 확인하는 것입니다. 여기서의 접근 방식이 pgrep정확할 수 있습니다.

스크립트에서는 작동하지만 대화식으로는 작동하지 않는 이유는 경쟁 조건일 수 있습니다. 첫 번째 프로세스를 ssh백그라운드에 두었기 때문에 셸과 ssh동시에 실행되고 sshCPU를 많이 사용하는 암호화 인증과 일부 네트워크 왕복을 수행합니다. pgrep스크립트에서 실행 중인 내용은 ssh<1>포크 자체가 백그라운드로 들어가기 전에 실행될 가능성이 높습니다. 이 문제를 해결하려면 pgrep나중에 sleep호출하거나 나중에 PID가 실제로 필요할 때 호출하여 실행하십시오.

ssh[1]: 기술적으로 클래식 이중 포크를 배경으로 사용하면 이보다 더 복잡해질 수 있습니다. 그럴 경우 ssh둘 사이에는 또 다른 짧은 과정이 있게 된다.

[2]: systemd모든 자녀를 추적하기 위해 cgroup이나 다른 것을 사용하지 않는 한. 하지만 당신은 그렇지 않습니다.

관련 정보