일부 bash 인스턴스 내에서 정확한 명령 줄이 실행되고 있는지 어떻게 알 수 있습니까?


29

루프 내에서 복잡한 명령 집합을 실행 하는 오래 실행되는 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. cmdline아래의 사용 정보 /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
    

    즉, ORIGINAL 명령 줄의 출력이 없습니다 while true ; do echo 1 ; echo 2>/dev/null ; sleep 30 ; done. 즉, 내가 찾고있는 것 입니다.

답변:


40

나는 빨대를 잡고 있다는 것을 알고 있었지만 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

나중에 쉽게 재사용 할 수 있도록 프로세스를 자동화 하는 bash 스크립트를 작성했습니다 .


1
아주 좋은 sleuthing +1. 2 일 후에 이것을 예외 A로 표시하십시오.
slm

@ slm : 감사합니다! 나는 그것에 대해 블로그 게시물을 쓸 것이다-재미, 이것을 사냥.
ttsiodras

1
작성한 Readline이 가능 당신은 또한이 작업을 수행 할 수 있습니다 gdb: print (char *)rl_line_buffer. 시퀀스의 현재 명령은 print (char *)the_printed_command입니다. 또한 call history_builtin()bash 프로세스의 tty에서 출력되므로 유용하지 않을 수 있습니다.
mr.spuratic

11
@slm : 저항 할 수 없음-블로그에 대한 내용 : users.softlab.ece.ntua.gr/~ttsiod/bashheimer.html
ttsiodras

1
bash는 안전합니까? gdb에서 무언가를 실행할 때 현재 실행중인 코드를 화나게하는 일부 내부 상태를 수정하지 않기를 바랍니다. 실제로 bash는 gdb로 일시 중단 할 때마다 자식 프로세스가 완료 될 때까지 기다리는 것입니다.
Adrian Pronk

5

명령이 여전히 화면에서 실행 중이므로 상위 bash는 히스토리를 다시 읽지 않았습니다.

  • 화면에 다시 부착
  • ^Z다음을 누르십시오up arrow
  • 보너스 : 명령을 작은 따옴표로 묶고 ( ^A^Ascreen-1 때문에-로 탐색 ^E) 파일에 echo + 리디렉션
  • fg 명령 실행을 추구

주의 사항이 있지만 이것은 대부분 유용합니다.


예, 심지어 죽이고를 누르십시오 up. 아무 문제없이 다시 시작할 것이라고 확신해야하지만, 그렇지 않으면 재부팅 후에도 같은 문제가 발생합니다. 가동 중지 시간이 문제가되지 않는 순간 만 선택하면됩니다.
Matthieu Napoli

0

나는 당신이 당신 자신의 대답을 찾았다는 것을 알고 있지만 다음과 같이 할 수없는 이유가 있습니다.

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

실제 작업의 출력과 현재 실행중인 행을 보여주는 bash의 출력을 함께 혼합 할 수는 없습니다.

또한 FWIW, 자세한 정보가 필요한 경우 set -o xtrace.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.