또는 ssh 명령에서 true를 사용합니다.

또는 ssh 명령에서 true를 사용합니다.

SSH를 통해 원격으로 실행 하려고 시도 pkill -f하고 가능한 오류 코드를 삭제하려고 하면(프로세스를 찾을 수 없더라도 나머지 스크립트를 계속 실행) || true예상한 대로 작동하지 않습니다.

$ pkill asdf || true
$ echo $?
0
$ pkill -f asdf || true
$ echo $?
0
$ ssh [email protected] "pkill asdf || true"
$ echo $?
0
$ ssh [email protected] "pkill -f asdf || true"
255

그렇게 생각해요SSH따옴표 사이의 명령 대신 255를 반환하는데 그 이유는 무엇입니까?

답변1

ssh자체적으로 255 종료 상태를 반환한다는 가정이 정확합니다 . 매뉴얼 ssh페이지에는 다음과 같이 명시되어 있습니다.

ssh는 원격 명령의 종료 상태로 종료되거나, 오류가 발생하면 255로 종료됩니다.

방금 실행하면 "에 해당하는 종료 상태를 얻을 가능성이 높습니다.ssh [email protected] "pkill -f asdf"1pkill일치하는 프로세스가 없습니다.".

어려운 부분은 이해이다SSH를 실행하는 동안 오류가 발생했습니다.

ssh [email protected] "pkill -f asdf || true"

SSH 원격 명령

SSH 서버는 원격 명령을 실행하기 위해 셸을 시작합니다. 실제적인 예는 다음과 같습니다.

$ ssh server "ps -elf | tail -5"
4 S root     35323  1024 12  80   0 - 43170 poll_s 12:01 ?        00:00:00 sshd: anthony [priv]
5 S anthony  35329 35323  0  80   0 - 43170 poll_s 12:01 ?        00:00:00 sshd: anthony@notty
0 S anthony  35330 35329  0  80   0 - 28283 do_wai 12:01 ?        00:00:00 bash -c ps -elf | tail -5
0 R anthony  35341 35330  0  80   0 - 40340 -      12:01 ?        00:00:00 ps -elf
0 S anthony  35342 35330  0  80   0 - 26985 pipe_w 12:01 ?        00:00:00 tail -5

기본 쉘은 이며 bash원격 명령은 간단한 명령이 아니라관로, "제어 연산자로 구분된 하나 이상의 명령 시퀀스 |".

Bash 쉘은 전달된 옵션이 다음과 같다는 것을 인식할 만큼 똑똑합니다 -c.간단한 명령, 실제로 새 프로세스를 분기하지 않음으로써 최적화할 수 있습니다. 즉, 실행 전에 exec추가 단계를 수행하는 대신 간단한 명령을 직접 실행합니다. 다음은 원격 단순 명령을 실행할 때 발생하는 일의 예입니다(이 경우).forkexecps -elf

$ ssh server "ps -elf" | tail -5
1 S root     34740     2  0  80   0 -     0 worker 11:49 ?        00:00:00 [kworker/0:1]
1 S root     34762     2  0  80   0 -     0 worker 11:50 ?        00:00:00 [kworker/0:3]
4 S root     34824  1024 31  80   0 - 43170 poll_s 11:51 ?        00:00:00 sshd: anthony [priv]
5 S anthony  34829 34824  0  80   0 - 43170 poll_s 11:51 ?        00:00:00 sshd: anthony@notty
0 R anthony  34830 34829  0  80   0 - 40340 -      11:51 ?        00:00:00 ps -elf

나는 이전에 이런 행동을 경험한 적이 있지만,이 AskUbuntu 답변.

삭제 동작

pkill -f asdf || true이것은 단순한 명령이 아니기 때문에 (명령 목록), 위의 최적화가 발생하지 않으므로 실행하면 프로세스가 분기되어 실행됩니다.ssh [email protected] "pkill -f asdf || true"sshdbash -c "pkill -f asdf || true"

ctx의 답변에서 알 수 있듯이 pkill자체 프로세스는 종료되지 않습니다. 그러나 그것은~ 할 것이다명령줄이 이 패턴과 일치 -f하는 다른 프로세스를 종료합니다. 명령 bash -c은 이 패턴과 일치하므로 이 프로세스, 즉 자체 상위 프로세스(발생하는 경우)를 종료합니다.

그런 다음 SSH 서버는 원격 명령을 실행하기 위해 시작한 셸 프로세스가 예기치 않게 종료되었음을 발견하고 SSH 클라이언트에 오류를 보고합니다.

답변2

원격 명령이 자동으로 종료됩니다.

$ ssh 10.0.3.70 'pgrep -af asdf'
$ ssh 10.0.3.70 'pgrep -af asdf || true'
1018 bash -c pgrep -af asdf || true

pgrep 및 pkill은 자체 프로세스를 무시하지만 -f 플래그를 사용하면 상위 쉘을 찾을 수 있습니다.

$ pgrep -af asdf
$ pgrep -af asdf || true
$ bash -c 'pgrep -af asdf'
$ bash -c 'pgrep -af asdf || true'
9803 bash -c pgrep -af asdf || true

답변3

pkill에게 "asdf"와 일치하는 항목을 모두 종료하도록 요청했습니다. "asdf"라는 이름의 항목은 계속 찾지만 자체적으로는 표시되지 않도록 [a]sdf와 일치하도록 지시해야 합니다(asdf를 [a]sdf와 정렬하는 경우 s는 ]와 정렬되고 그렇지 않음에 유의하세요 .)

ssh 10.0.3.70 'pgrep -af "[a]sdf" || true'

이는 grep/egrep/awk/etc에서도 사용되는 일반적인 트릭입니다.

ps -ef | grep "something"  # will sometimes match itself too
ps -ef | grep "[s]omething" # will not match itself

# why it works:
# the commandline contains:     ps -ef | grep [s]omething
# and grep tries to find:                      something

이 팁은 오래된 것입니다. 수십 년 전에 Unix FAQ에서 본 것입니다(아직도 읽을 가치가 있습니다!).

"자동화"하는 것은 쉽지 않지만 일반적으로 변수 문자열 regexp="something" 을 grep해야 할 때마다 다음을 수행해 볼 수 있습니다.

grep "$(echo "${regexp}" | LC_ALL='C' sed -e 's/[a-zA-Z0-9_-]/[&]/')" 
#  if regexp="something",  it does: grep "[s]omething"
#  if regexp="otherthing", it does: grep "[o]therthing"
#  if regexp="^thirdthing", it does: grep "^[t]hirdthing" #ok, kept the "^"
#BUT fails on : regexp="[abc]def", as it does: grep "[[a]bc]def" instead of grep "[abc][d]ef" ...

관련 정보