쉘 스크립트가 어떤 프로그램을 실행했는지 알 수있는 방법이 있습니까?


13

* nix 세계에서 쉘 스크립트가 어떤 프로그램을 실행했는지에 대한 정보를 얻을 수있는 방법이 있습니까?


예:

/path/to/script1 /path/to/script_xyz

이 가상 시나리오에서 script_xyz경로 정보를 가질 것입니다 ( /path/to/script1)

또는

프로세스 PID

그것을 실행 한 실체의.

참고 : 다른 솔루션과 접근법에 대해 궁금합니다. 실제로 이것이 가능할 것으로 기대하지는 않습니다.


3
주제는 어떤 프로그램 이 스크립트를 실행 했는지 묻습니다 . 그러나 실제 질문은 스크립트 의 통역사 를 요구하는 것 같습니다 . 귀하의 질문에 대한 두 가지 중 어느 것입니까?
kasperd

@kasperd 당신이 맞아요. 질문은 프로그램에 관한 것이지만 실제로는 통역사입니다. 그렇기 때문에 처음에는 이것이 불가능하다고 생각했습니다.
Miloš Đakonović

답변:


23

프로세스 포크와 실행 사이에는 종종 혼동이 있습니다.

bash쉘 프롬프트에서 할 때 .

$ sh -c 'exec env ps'

프롬프트를 발행하는 프로세스 P1$ 이 현재 bash코드를 실행 중 입니다. 이 bash코드 는 실행 된 새로운 프로세스 P2 를 분기 한 다음 실행된다 ./bin/sh/usr/bin/env/bin/ps

그래서 P2는 차례의 코드를 실행 한 bash, sh, envps.

ps(또는 여기서 대신 사용할 스크립트와 같은 다른 명령)은 env명령에 의해 실행되었음을 알 수있는 방법이 없습니다 .

이 할 수있는 모든 부모 프로세스 ID 중 하나가 될 것이다이 경우, 이는 무엇인지 찾을 수있다 P1 또는 1경우 P1이 다른 프로세스 간격으로 또는 Linux에서 사망 한로 지정되어 그 subreaper 대신1 .

그런 다음 시스템에서 현재 해당 프로세스가 실행중인 명령 ( readlink /proc/<pid>/exeLinux에서 와 같이 ) 또는 마지막으로 실행 된 명령으로 전달 된 인수 (와 같은)를 시스템에 쿼리 할 수 ​​있습니다 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".


8

예, 프로그램은 부모가 누구인지 알 수 있습니다.

예를 들어, 두 개의 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의 답변을 참조하십시오 .


감사. 귀하의 예를 들어 내가 얻을 스크립트 실행 s1, s2그리고 PPID이후 여러 줄에 다음 값 만을 ERROR: Unsupported SysV option.빈 값 - 추가 설명과 여러 라인Parent command
밀로스 Đakonović

John이 플랫폼에서 사용할 수 없거나 다르게 제공되는 일부 ps 기능을 사용하고 있다면 ps (1) 매뉴얼 페이지를 확인하십시오.
Jasen

@Miloshio 패키지 버전 3.3.12 ps에서 위의 내용을 테스트했습니다 procps-ng. Jasen이 제안한 것처럼 부모의 명령 줄을 인쇄하기 위해 다른 구문이 필요할 수있는 다른 버전을 사용하고있을 가능성이 있습니다. 시도하십시오 ps -f | grep $PPID.
John1024
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.