![이전에 실행된 SSH 명령의 PID 예측](https://linux55.com/image/73313/%EC%9D%B4%EC%A0%84%EC%97%90%20%EC%8B%A4%ED%96%89%EB%90%9C%20SSH%20%EB%AA%85%EB%A0%B9%EC%9D%98%20PID%20%EC%98%88%EC%B8%A1.png)
이것은 가장 이상한 것입니다.
스크립트에서는 다음과 같이 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는 결코 동일하지 않으며, 스크립트에서 일련의 명령이 실행될 때에도 마찬가지입니다.
왜 이런 일이 발생하는지 설명할 수 있나요? 나는 이것이 실제로 다른 프로세스를 분기하는 초기 호출 때문일 수 있다고 생각했지만
ssh
왜 스크립트 내부에서 작동합니까?$!
이것은 또한 스크립트에서ssh
PID를 얻기 위해 위에서 설명한 방법을 사용하는 것이 실제로 항상 작동할지 여부에 대한 의문을 갖게 합니다 (지금까지는 작동했지만). 이게 정말 믿을 만한 걸까요?pgrep
사용하는 것보다 "깨끗하다" 고 생각합니다 ...
답변1
쉘의 $!
변수는 쉘에 의해 시작된 프로세스의 pid만 알고 있습니다. 예상한 대로 호출은 자체 프로세스의 포크를 ssh
사용하여 이루어 -f
지므로 백그라운드로 이동할 수 있으므로 전체 프로세스 트리는 [1]과 같습니다.
shell
|
+--ssh<1> (pid is $!)
|
+--ssh<2> (pid is different)
ssh<1>
호출 직후 종료되므로 의 값은 $!
유용하지 않습니다. ssh<2>
원격 통신과 터널 설정을 담당하며 PID를 안정적으로 얻는 유일한 방법은 [ pgrep
2]에서 했던 것처럼 프로세스 테이블을 확인하는 것입니다. 여기서의 접근 방식이 pgrep
정확할 수 있습니다.
스크립트에서는 작동하지만 대화식으로는 작동하지 않는 이유는 경쟁 조건일 수 있습니다. 첫 번째 프로세스를 ssh
백그라운드에 두었기 때문에 셸과 ssh
동시에 실행되고 ssh
CPU를 많이 사용하는 암호화 인증과 일부 네트워크 왕복을 수행합니다. pgrep
스크립트에서 실행 중인 내용은 ssh<1>
포크 자체가 백그라운드로 들어가기 전에 실행될 가능성이 높습니다. 이 문제를 해결하려면 pgrep
나중에 sleep
호출하거나 나중에 PID가 실제로 필요할 때 호출하여 실행하십시오.
ssh
[1]: 기술적으로 클래식 이중 포크를 배경으로 사용하면 이보다 더 복잡해질 수 있습니다. 그럴 경우 ssh
둘 사이에는 또 다른 짧은 과정이 있게 된다.
[2]: systemd
모든 자녀를 추적하기 위해 cgroup이나 다른 것을 사용하지 않는 한. 하지만 당신은 그렇지 않습니다.