bash 스크립트(첫 번째 줄 #! /bin/bash
) 가 있고 do-doruns
bash 명령줄에서 호출합니다../do-doruns arg1 arg2 ...
이 스크립트는 차례로 scripts 를 호출 ./dorun a1 a2 a3 ...
하며 더 많은 수준의 스크립트가 있으며 컴파일된 프로그램을 호출합니다.
ps
및 를 사용하여 보면 dorun
그 아래에서 호출되는 모든 실행 중인 항목에는 ps
해당 이름과 명령줄 인수가 표시됩니다. 예를 들어 다음과 같습니다.
/bin/bash /home/moss/path-to-dorun/dorun a1 a2 a3
등. 그러나 어떤 do-doruns
선도 표시되지 않습니다. 확실히 실행 중입니다(하위 프로세스가 완료되기를 기다리고 있음). 왜 그랬는지 이해할 수 있어논쟁사라질 수 있지만(별도의 테스트에서 shift
bash를 사용하면 인수가 사라지지 않는 것으로 나타났지만 ps
) 해당 $0
명령 이름은 사라지지 않습니다.
이것이 내 작업에 방해가 되는 것은 아니지만, 꼭 알고 싶은 이상한 미스터리입니다. 사물의 버전은 다음과 같습니다.
uname -a
보여주다:Linux moss-Ubuntu-SMCSim 5.4.0-81-generic #91-Ubuntu SMP Thu Jul 15 19:09:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
bash --version
보여주다:GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
ps --version
표시되는 내용(아마도 이상하게도):ps from procps-ng UNKNOWN
이 동작은 이에 국한되지 않고
ps
더top
기본적으로 보이도록 표시됩니다.마지막으로, 이것이 중요하다면 이 모든 것이 VirtualBox 가상 머신에서 실행되고 있다는 것입니다.
vboxmanage --version
보여주다:7.0.4r154605
답변1
ps -C
이는 options 에서 사용하는 명령 이름을 변경 하고 grep과 일치하는 방법(사용하는 플래그에 따라 다름)을 변경하므로 스크립트의 첫 번째 줄이 어떻게 보이는지에 따라 달라질 수 있습니다 .
다음과 같은 것을 사용하십시오
#!/bin/bash
명령 이름을 스크립트 이름으로 변경하므로 do-dorun으로 표시됩니다.
사용
#!/bin/env bash
이는 명령 이름이 bash로 유지됨을 의미합니다.
두 가지 모두에 대한 명령줄은 동일하게 보입니다. 예를 들어/bin/bash myscriptname.sh arg1 arg2 arg3
답변2
eval
추가 연구, 즉 스크립트를 최소한의 테스트 사례로 축소한 결과 이 동작은 bash의 내장 기능을 사용했기 때문에 발생한 것으로 나타났습니다 . 최소 테스트 케이스는 다음과 같습니다.
#! /bin/bash
eval foo xyz
foo
실행할 다른 스크립트는 어디에 있습니까? (특별히 테스트하지는 않았지만 프로그램에서도 이런 일이 발생할 수 있습니다.)
무슨 일이 일어나고 있는 것 같으면 eval
쉘이 명령줄 옵션 fork-exec a를 bash
사용하여 명령줄을 실행하게 만드는 것입니다. -c
그러한 bash 호출로 인해 명령줄에 빈 작업이 표시되는 것 같습니다. 명령줄을 읽은 다음 bash는 필요한 프로그램만 실행하기 때문인 것 같습니다.
그래서 이런 동작을 원하지 않는다면 eval
.
알아낼 수 있도록 도와주셔서 감사합니다!
답변3
exec
후속 명령이 exec
호출 쉘을 대체하므로 쉘의 명령줄을 변경하는 쉬운 방법이 있습니다 . /proc/pid/cmdline
여기서 인쇄물을 아름답게 한다는 의견을 고려하면 버전 2입니다. 그러나 eval을 사용하여 변수에 준비된 명령을 실행하는 방법이 exec
.
예시 v2:
#!/bin/bash
identifyMyself() {
echo "My cmdline: $0 My arg1: $1 My PID: $BASHPID"
echo "Kernel says:"
#cat -A /proc/$BASHPID/cmdline
#echo
readarray -d '' -t cmdline < /proc/$$/cmdline
#declare -p cmdline
printf '%s ' "${cmdline[@]}"
echo
}
identifyMyself "$1"
if [ -z "$1" ]
then
echo "calling myself with long parameters"
"$0" arg1 arg2 arg3 arg4
fi
if [ -z "$1" ]
then
dorun="$0 arg1 arg2 arg3 arg4"
echo "calling myself with long parameters by evaling a variable"
eval "${dorun}"
fi
if [ -z "$1" ]
then
echo "I am still here"
identifyMyself "$1"
fi
if [ -z "$1" ]
then
echo "execing myself with long parameters"
exec "$0" arg1 arg2 arg3 arg4
fi
if [ -z "$1" ]
then
echo "now I am gone"
identifyMyself "$1"
fi
산출:
$ ./bashtestv2_pid.sh
My cmdline: ./bashtestv2_pid.sh My arg1: My PID: 1444428
Kernel says:
/bin/bash ./bashtestv2_pid.sh
calling myself with long parameters
My cmdline: ./bashtestv2_pid.sh My arg1: arg1 My PID: 1444429
Kernel says:
/bin/bash ./bashtestv2_pid.sh arg1 arg2 arg3 arg4
calling myself with long parameters by evaling a variable
My cmdline: ./bashtestv2_pid.sh My arg1: arg1 My PID: 1444430
Kernel says:
/bin/bash ./bashtestv2_pid.sh arg1 arg2 arg3 arg4
I am still here
My cmdline: ./bashtestv2_pid.sh My arg1: My PID: 1444428
Kernel says:
/bin/bash ./bashtestv2_pid.sh
execing myself with long parameters
My cmdline: /home/user/bin/bashtestv2_pid.sh My arg1: arg1 My PID: 1444428
Kernel says:
/bin/bash /home/user/bin/bashtestv2_pid.sh arg1 arg2 arg3 arg4
명령줄이 변경되면 실행 후 PID가 어떻게 동일하게 유지되는지 확인하세요. eval
일반 통화처럼 작동합니다 . 귀하께서 댓글에서 말씀하신 내용은 다음과 같습니다. 그러나 당신 자신의 대답에서는 정반대라고 말합니다. 암시 eval
적 exec
.