*nix 세계에서 쉘 스크립트가 어떤 프로그램을 실행했는지에 대한 정보를 얻을 수 있는 방법이 있습니까?
예:
/path/to/script1 /path/to/script_xyz
이 가상 시나리오에서는 경로 정보( ) script_xyz
가 있습니다 ./path/to/script1
또는
프로세스 PID
이를 실행하는 엔터티입니다.
참고: 다양한 솔루션과 접근 방식이 궁금합니다. 실제로는 가능하지 않을 것 같습니다.
답변1
프로세스 분기와 실행 사이에 혼란이 자주 발생합니다.
쉘 프롬프트에서 이 작업을 수행할 때 bash
.
$ sh -c 'exec env ps'
프로세스P1$
코드가 현재 실행 중인 동안 이 프롬프트를 발행하십시오 bash
. 이 bash
코드는 새로운 프로세스를 포크합니다P2하고 /bin/sh
또 하고 /usr/bin/env
또 하세요 /bin/ps
.
그래서P2bash
, sh
, 의 코드 env
가 순서대로 실행됩니다 ps
.
ps
env
(또는 여기서 사용하는 스크립트와 같은 다른 명령) 은 명령이 실행되었는지 여부를 알 수 없습니다 .
할 수 있는 일은 상위 프로세스 ID가 무엇인지 알아내는 것뿐입니다. 이 경우에는P1아니면 1
만약에P1이 간격 내에 사망했거나 Linux에서는 다음과 같이 지정된 다른 하나가 사망했습니다.대리 사신바꾸다 1
.
그런 다음 프로세스가 어떤 명령인지 시스템에 쿼리할 수 있습니다.지금실행 중이거나( readlink /proc/<pid>/exe
Linux에서와 같이) 실행한 마지막 명령에 전달된 인수(Linux에서와 같이 ps -o args= -p <pid>
).
스크립트가 무엇을 호출했는지 알기를 원하는 경우 호출자에게 이를 알려주는 것이 신뢰할 수 있는 방법입니다. 예를 들어 환경 변수를 통해 이 작업을 수행할 수 있습니다. 예를 들어 다음 script1
과 같이 작성할 수 있습니다.
#! /bin/sh -
INVOKER=$0 script2 &
그리고 script2
:
#! /bin/sh -
printf '%s\n' "I was invoked by $INVOKER"
# and in this case, we'll probably find the parent process is 1
# (if not now, at least one second later) as script1 exited just after
# invoking script2:
ps -fp "$$"
sleep 1
ps -fp "$$"
exit
$INVOKER
할 것이다(일반적으로 말하면)에는 에 대한 경로가 포함되어 있습니다 script1
. 어떤 경우에는 상대 경로일 수 있으며 경로는 시작 시 현재 작업 디렉터리에 상대적입니다 script1
. 따라서 script1
호출하기 전에 현재 작업 디렉토리를 변경 하면 해당 디렉토리 script2
가 script2
호출된 위치에 대한 잘못된 정보를 얻게 됩니다. 따라서 $INVOKER
다음과 같이 절대 경로(기본 이름을 유지하는 것이 좋음)를 포함하는 것이 가장 좋습니다 script1
.
#! /bin/sh -
mypath=$(
mydir=$(dirname -- "$0") &&
cd -P -- "$mydir" &&
pwd -P) && mypath=$mypath/$(basename -- "$0") || mypath=$0
... some code possibly changing the current working directory
INVOKER=$mypath script2
POSIX 쉘에는 $PPID
쉘이 초기화될 때 쉘을 실행한 상위 프로세스의 pid가 포함됩니다. 나중에 위와 같이 ID가 있는 프로세스가 $PPID
종료되면 상위 프로세스가 변경될 수 있습니다.
zsh
zsh/system
모듈 에서 쿼리할 수 있습니다.현재의현재(하위) 쉘의 상위 pid로, 접미사가 붙습니다 $sysparams[ppid]
. POSIX 쉘에서는 다음을 얻을 수 있습니다.현재의인터프리터를 실행하는 프로세스의 ppid(아직 실행 중이라고 가정) ps -o ppid= -p "$$"
. 를 사용하여 bash
현재 (하위)쉘의 ppid를 얻을 수 있습니다 ps -o ppid= -p "$BASHPID"
.
답변2
예, 프로그램은 상위 프로그램이 누구인지 알 수 있습니다.
이를 설명하기 위해 두 개의 bash 스크립트를 만듭니다. 첫 번째 스크립트는 PID를 보고하고 두 번째 스크립트를 시작합니다.
$ cat s1.sh
#!/bin/bash
echo s1=$$
bash s2.sh
두 번째 스크립트는 프로세스 ID, 상위 프로세스의 PID 및 상위 프로세스를 실행하는 데 사용되는 명령줄을 보고합니다.
$ cat s2.sh
#!/bin/bash
echo s2=$$ PPID=$PPID
echo "Parent command: $(ps -o cmd= -q $PPID)"
이제 실행해 보겠습니다.
$ bash s1.sh
s1=17955
s2=17956 PPID=17955
Parent command: bash s1.sh
보시다시피 두 번째 스크립트는 실제로 상위 스크립트의 PID를 알고 있습니다. 사용된 ps
이 PID는 상위를 호출하는 데 사용되는 명령줄을 표시합니다.
PPID에 대한 더 자세한 내용은 Stéphane Chazelas의 글을 참조하세요.답변.