GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie bestimmen Sie den tatsächlichen Befehl, der in Sie einfließt?

die Pipe erscheint als Eintrag in der Liste der offenen Dateideskriptoren Ihres Prozesses:

 % 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

Sie könnten auch so etwas verwenden wie:

 % 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

Also, dann hast du den Inode der Pipe :) Du kannst jetzt jeden anderen Prozess unter /proc/ durchsuchen für dieses Rohr. dann haben Sie den Befehl, der zu Ihnen geleitet wird:

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

in diesem Beispiel cat zu den Stationen sh geleitet . in /proc/29889 finden Sie eine Datei namens cmdline was dir sagt, was genau hieß:

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

die Felder der Kommandozeile sind durch NUL getrennt, dadurch sieht es etwas hässlich aus :)


Akira schlug vor, lsof zu verwenden .

So könnten Sie es skripten:

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

Ausführen:

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

Eine andere Möglichkeit ist die Verwendung von Prozessgruppen.

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

Ausführen:

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

Beachten Sie, dass beide nur funktionieren, wenn der Befehl auf der linken Seite der Pipe lange genug für ps ausgeführt wird Es zu sehen. Sie sagten, Sie würden es mit tail -f verwenden , daher bezweifle ich, dass dies ein Problem ist.

$ sleep 0 | ./whatpipe1.sh 

$ sleep 1 | ./whatpipe1.sh
sleep 1

Linux
  1. Wie verwende ich den basename-Befehl?

  2. Wie führe ich einen Befehl aus, der Umleitung oder Piping mit Sudo beinhaltet?

  3. Wie kann man die Zeichencodierung bestimmen, die ein Terminal in einem C/c++-Programm verwendet?

  4. Wie können Sie installierte Versionen der glibc-Bibliotheken ermitteln?

  5. Wie kann ich die Ausgabe eines Befehls direkt in meine Zwischenablage kopieren?

So verwenden Sie den Linux-Grep-Befehl

So verwenden Sie den Verlaufsbefehl unter Linux

So verwenden Sie den Linux-Verlaufsbefehl

Linux-Dateibefehl:So bestimmen Sie den Dateityp in Linux

So verwenden Sie den Bash-Lesebefehl

So verwenden Sie den Linux-xargs-Befehl