자신에게 배관중인 실제 명령을 어떻게 결정합니까?


9

라는 bash 스크립트가 있다고 가정 해 봅시다 log.sh. 이 스크립트에서는 파이프에서 입력을 읽고 싶지만 입력을 파이프로 보내는 데 사용되는 명령을 알고 싶습니다. 예:

tail -f /var/log/httpd/error | log.sh

쉘 스크립트에서 나는 명령을 알고 싶다 tail -f /var/log/httpd/error.


왜 당신이 이것을 원하는지 궁금합니다.
Ignacio Vazquez-Abrams

내 생각에 pid를 캡처하고 처리하는 GUI 프로그램을 작성하고 있습니까?
palbakulich

결과를 넣을 위치를 구별 할 수 있도록 알고 싶습니다. 명령과 파일 이름에 따라 다른 작업을 수행하고 싶습니다.
세인트 존 존슨

4
그것은 저에게 깜짝 원칙의 주요 위반으로 보입니다. 스크립트가 다른 환경에서 다른 작업을 수행해야하는 경우 입력이 시작되는 위치가 아니라 명령 행 옵션으로 제어해야합니다.
Dave Sherohman

@Dave, 동의합니다. 이 예제를 위해 들어오는 명령이 무엇인지 '알고 싶습니다'.
세인트 존 존슨

답변:


7

Akira는을 (를) 사용하도록 제안했습니다 lsof.

스크립트를 작성하는 방법은 다음과 같습니다.

whatpipe2.sh

#!/bin/bash

pid=$$
pgid=$(ps -o pgid= -p $pid)
lsofout=$(lsof -g $pgid)
pipenode=$(echo "$lsofout" | awk '$5 == "0r" { print $9 }')
otherpids=$(echo "$lsofout" | awk '$5 == "1w" { print $2 }')
for pid in $otherpids; do
    if cmd=$(ps -o cmd= -p $pid 2>/dev/null); then
        echo "$cmd"
        break
    fi
done

그것을 실행 :

$ tail -f /var/log/messages | ./whatpipe2.sh
tail -f /var/log/messages
^C

다른 방법은 프로세스 그룹을 사용하는 것입니다.

whatpipe1.sh

#!/bin/bash    

pid=$$
# ps output is nasty, can (and usually does) start with spaces
# to handle this, I don't quote the "if test $_pgrp = $pgrp" line below
pgrp=$(ps -o pgrp= -p $pid)
psout=$(ps -o pgrp= -o pid= -o cmd=)
echo "$psout" | while read _pgrp _pid _cmd; do
    if test $_pgrp = $pgrp; then
        if test $_pid != $pid; then
            case $_cmd in
            ps*)
                # don't print the "ps" we ran to get this info
                # XXX but this actually means we exclude any "ps" command :-(
                ;;
            *)
                echo "$_cmd"
                ;;
            esac
        fi
    fi
done

그것을 실행 :

$ tail -f /var/log/messages | ./whatpipe1.sh
tail -f /var/log/messages
^C

파이프 왼쪽의 명령이 파이프 ps를 볼 수 있을 정도로 오랫동안 실행될 경우에만 작동 합니다. 와 함께 사용한다고 말 tail -f했으므로 이것이 문제인 것 같습니다.

$ sleep 0 | ./whatpipe1.sh 

$ sleep 1 | ./whatpipe1.sh
sleep 1

이 거대한 게시물 대신 lsof 기반 스크립트로 두 번째 답변을했을 것입니다. 저것에 대한 좋은 일.
akira

감사합니다. 깨끗하고 휴대하기 쉽도록 몇 차례 시도했습니다. 그 과정에서 procfs와 lsof에 대해 몇 가지를 배웠습니다. 아이디어 주셔서 감사합니다.
Mikel

다른 사람들이 직접 사용할 수있는 답변을 제공하므로 귀하의 의견을 수락했습니다. @Akira, 당신은 대부분의 작업을 수행했습니다. 죄송합니다.
세인트 존 존슨

10

파이프는 프로세스의 열린 파일 설명자 목록에 항목으로 나타납니다.

 % ls -l /proc/PID/fd
 lr-x------ 1 xyz xyz 64 Feb 11 08:05 0 -> pipe:[124149866]
 lrwx------ 1 xyz xyz 64 Feb 11 08:05 1 -> /dev/pts/2
 lrwx------ 1 xyz xyz 64 Feb 11 08:05 2 -> /dev/pts/2
 lr-x------ 1 xyz xyz 64 Feb 11 08:05 10 -> /tmp/foo.sh

다음과 같은 것을 사용할 수도 있습니다.

 % lsof -p PID
 sh      29890 xyz  cwd    DIR   0,44    4096  77712070 /tmp
 sh      29890 xyz  rtd    DIR   0,44    4096  74368803 /
 sh      29890 xyz  txt    REG   0,44   83888  77597729 /bin/dash
 sh      29890 xyz  mem    REG   0,44 1405508  79888619 /lib/tls/i686/cmov/libc-2.11.1.so
 sh      29890 xyz  mem    REG   0,44  113964  79874782 /lib/ld-2.11.1.so
 sh      29890 xyz    0r  FIFO    0,6         124149866 pipe
 sh      29890 xyz    1u   CHR  136,2                 4 /dev/pts/2
 sh      29890 xyz    2u   CHR  136,2                 4 /dev/pts/2
 sh      29890 xyz   10r   REG   0,44      66  77712115 /tmp/foo.sh

따라서 파이프의 inode가있는 것보다 :) 이제 /proc/해당 파이프 에 대한 다른 모든 프로세스를 검색 할 수 있습니다 . 그러면 당신에게 배관 명령이있을 것입니다 :

 % lsof | grep 124149866 
 cat     29889 xyz    1w  FIFO                0,6          124149866 pipe
 sh      29890 xyz    0r  FIFO                0,6          124149866 pipe

이 예에서는 catwards로 파이프되었습니다 sh. 에 /proc/29889당신이라는 파일을 찾을 수 있습니다 cmdline정확히 불렀다 무엇을 알려줍니다 :

 % cat /proc/29889/cmdline
 cat/dev/zero%  

명령 줄의 필드는 NUL로 구분되므로 약간 추한 것처럼 보입니다. :)


어떤 답변을 수락해야할지 모르겠습니다. @Akira, 당신은 그것을 결정하는 방법에 대한 실제 분석을 제공했지만 @Mikel은 나에게 스크립트를 주었다. 일을 굉장히 어렵게 만드는 방법.
세인트 존 존슨

1

lsof최신 Linux 배포판을 사용하는 컴팩트 솔루션은 다음과 같습니다 .

cmd=$(lsof -t -p $$ -a -d 0 +E | while read p; do
    [ $p -ne $$ ] && echo "$(tr \\000 " " </proc/$p/cmdline)"
done)

+E현재 쉘 프로세스 ( -p $$ -a -d 0)에서 FD 0 의 엔드 포인트 파일 ( )을 나열한 다음 출력을 PID로만 제한 ( -t)하여 파이프의 양쪽에 PID를 생성합니다.

참고 :

  1. 이상의 PID 소스 끝에서 발견 한, 예를 들어이있을 수 있습니다 { echo Hi; sleep 5 ; } | whatpipe.sh가능성이 산출됩니다 bash(입력 서브 쉘을)과 sleep 5.
  2. +Elsof로 컴파일 된 경우에만 사용할 수 있습니다 -DHASUXSOCKEPT. 대부분의 최신 Linux 배포판에는 적용되지만 어쨌든 설치를 확인하십시오.lsof -v 2>&1 | grep HASUXSOCKEPT
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.