Bash 인스턴스에서 실행되는 정확한 명령줄을 어떻게 확인할 수 있나요?

Bash 인스턴스에서 실행되는 정확한 명령줄을 어떻게 확인할 수 있나요?

루프 내에서 복잡한 명령 세트를 실행하는 장기 실행 bash인스턴스( 세션 내) 가 있습니다 (각 루프는 파이프, 리디렉션 등을 수행함).screen

긴 명령줄은 터미널 내부에 작성되며 스크립트 내부에는 없습니다. 이제 bash 프로세스 ID를 알고 루트 액세스 권한이 생겼습니다. 여기에서 실행된 정확한 명령줄을 어떻게 볼 수 있습니까 bash?

bash$ echo $$
1234
bash$ while true ; do \
    someThing | somethingElse 2>/foo/bar | \
    yetAnother ; sleep 600 ; done

다른 셸 인스턴스에서 PID 1234 내에서 실행되는 명령줄을 보고 싶습니다.

bash$ echo $$
5678
bash$ su -
sh# cd /proc/1234
sh# # Do something here that will display the string  \
   'while true ; do someThing | somethingElse 2>/foo/bar | \
    yetAnother ; sleep 600 ; done'

가능합니까?

편집 #1

내가 얻은 답변 중 일부에 반례를 추가합니다.

  1. cmdlineunder 사용과 관련하여 /proc/PID: 적어도 내 시나리오에서는 작동하지 않습니다. 간단한 예는 다음과 같습니다.

    $ echo $$
    8909
    
    $ while true ; do echo 1 ; echo 2>/dev/null ; sleep 30 ; done
    

    다른 쉘에서:

    $ cat /proc/8909/cmdline
    bash
    
  2. 또한 쓸모가 없습니다 ps -p PID --noheaders -o cmd:

    $ ps -p 8909 --no-headers -o cmd
    bash
    
  3. ps -eaf또한 도움이 되지 않습니다:

    $ ps -eaf | grep 8909
    ttsiod    8909  8905  0 10:09 pts/0    00:00:00 bash
    ttsiod   30697  8909  0 10:22 pts/0    00:00:00 sleep 30
    ttsiod   31292 13928  0 10:23 pts/12   00:00:00 grep --color=auto 8909
    

    즉, 원시 명령줄에는 출력이 없습니다. 이는 바로 제가 찾고 있는 것입니다 while true ; do echo 1 ; echo 2>/dev/null ; sleep 30 ; done. 즉 .

답변1

나는 내가 지푸라기라도 잡고 있다는 것을 알고 있지만 UNIX는 결코 실패하지 않습니다!

이것이 내가 처리하는 방법입니다.

bash$ gdb --pid 8909
...
Loaded symbols for /lib/i386-linux-gnu/i686/cmov/libnss_files.so.2
0xb76e7424 in __kernel_vsyscall ()

그런 다음 (gdb)프롬프트에서 명령을 실행하여 call write_history("/tmp/foo")기록을 파일에 기록합니다 /tmp/foo.

(gdb) call write_history("/tmp/foo")
$1 = 0

그런 다음 프로세스를 중단합니다.

(gdb) detach
Detaching from program: /bin/bash, process 8909

그리고 종료합니다 gdb.

(gdb) q

정말...

bash$ tail -1 /tmp/foo
while true ; do echo 1 ; echo 2>/dev/null ; sleep 30 ; done

향후 재사용을 용이하게 하기 위해 다음과 같이 작성했습니다.배쉬 스크립트, 프로세스를 자동화합니다.

답변2

명령이 화면에서 계속 실행 중이므로 해당 상위 bash는 아직 기록을 다시 읽지 않았습니다. 따라서 다음과 같습니다.

  • 화면에 다시 연결
  • ^Z그런 다음 누르세요up arrow
  • 보너스: 명령을 작은따옴표로 묶으십시오( ^A^A-를 사용하십시오. 왜냐하면 screen(1) - 및 ^E)를 탐색하고 에코 + 파일로 리디렉션하기 때문입니다.
  • fg명령 실행 추구

몇 가지 주의 사항이 있지만 대부분의 경우 이는 충분히 유용합니다.

답변3

나는 당신이 자신의 답을 찾았다는 것을 알고 있지만 이것을 할 수 없는 이유가 있습니까?

(set -x; for f in 1 2 3 4 ; do  echo "$f"; sleep $f; done)

어쩌면 실제 작업의 출력과 현재 실행된 라인을 보여주는 bash 출력을 혼합할 수 없을 수도 있습니다.

또한 FWIW, 자세한 내용을 좋아한다면 set -o xtrace.

관련 정보