Nasłuchuj wyjścia z procesu podanego pid $$

16

Powiedz, że mam pid w ręku mypid=$$

czy jest jakaś komenda bash / system, której mogę użyć, by nasłuchiwać wyjścia z tego procesu z danym pid?

Jeśli nie istnieje żaden proces z mypid, myślę, że polecenie powinno po prostu zawieść.

Alexander Mills
źródło
Nie używam C #, ale najwyraźniej musi istnieć sposób: msdn.microsoft.com/en-us/library/fb4aw7b8(v=vs.110).aspx
Alexander Mills
W Uniksie często zdarza się czekać na procesy potomne korzystające waitz funkcji powłoki lub wait()biblioteki C. AFAIK nie ma standardowego sposobu oczekiwania na proces niebędący dzieckiem. Ponadto nie jest jasne, czy funkcja C # może to zrobić (zależy od tego, czym jest „powiązany proces”).
Kusalananda
Mógłbym to zrobić z ankietą, ale byłoby to okropne
Alexander Mills
Mogłoby to również potencjalnie dać złe wyniki. Ponowne użycie PID może teoretycznie oznaczać, że proces ożyje z tym samym PID, co proces, na który czekasz. W systemie Linux (z sekwencyjnymi PID) byłoby to mało prawdopodobne , ale w systemach takich jak OpenBSD (losowy przydział PID) byłby to problem.
Kusalananda

Odpowiedzi:

21

Dostałem to, czego potrzebowałem od tej odpowiedzi: https://stackoverflow.com/a/41613532/1223975

.. wyłączy się przy użyciu wait <pid> będzie działać tylko wtedy, gdy ten pid jest procesem potomnym bieżącego procesu .

Jednak dla każdego procesu będą działać następujące czynności:

Poczekaj na zakończenie dowolnego procesu

Linux:

tail --pid=$pid -f /dev/null

Darwin (wymaga, aby $pidmieć otwarte pliki):

lsof -p $pid +r 1 &>/dev/null

Z limitem czasu (sekundy)

Linux:

timeout $timeout tail --pid=$pid -f /dev/null

Darwin (wymaga, aby $pidmieć otwarte pliki):

lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)
Alexander Mills
źródło
Nie jest związany z Linuksem, jest cechą ogona GNU. Będzie więc działał na każdym systemie z ogonem GNU, takim jak GNU / Linux, i nie działałby na systemach nie opartych na GNU Linux.
Stéphane Chazelas
Obawiam się, że tail / lsof użyje odpytywania w tym przypadku, przynajmniej biorąc pod uwagę empiryczne dowody, że tak wygląda na MacOS.
Alexander Mills
lsof + r przełącza go w tryb powtarzania, dzięki czemu polecenie powtarza się co sekundę, więc używa odpytywania, cholera
Alexander Mills
3

Możesz użyć wbudowanego basha wait:

$ sleep 10 &
[2] 28751
$ wait 28751
[2]-  Done                    sleep 10
$ help wait
wait: wait [-n] [id ...]
    Wait for job completion and return exit status.

    Waits for each process identified by an ID, which may be a process ID or a
    job specification, and reports its termination status.  If ID is not
    given, waits for all currently active child processes, and the return
    status is zero.  If ID is a a job specification, waits for all processes
    in that job's pipeline.

    If the -n option is supplied, waits for the next job to terminate and
    returns its exit status.

    Exit Status:
    Returns the status of the last ID; fails if ID is invalid or an invalid
    option is given.

Wykorzystuje wywołanie systemowe waitpid().

$ whatis waitpid
waitpid (2)          - wait for process to change state
Derek Callaway
źródło
miło, że to działa dla mnie, mam nadzieję, że nie używa odpytywania pod maską, dzięki!
Alexander Mills
1
tak, nie będzie działać w moim przypadku użycia, pojawia się ten błąd: bash: wait: pid 47760 is not a child of this shell... z powrotem do deski kreślarskiej lol
Alexander Mills
Mam odpowiedź, właśnie wysłałem to dzięki
Alexander Mills
2
Będzie to tylko czekało na procesy potomne, a nie na proces niezwiązany z bieżącym procesem.
Kusalananda
1

Jeśli chodzi o https://stackoverflow.com/a/41613532/1223975 rozwiązanie, które Timeout in Seconds Darwinopublikował Alexander Mills , jest to obejście dla systemu operacyjnego typu UNIX, który nie ma GNU tail. Nie jest on specyficzny dla Darwin, ale w zależności od wieku systemu operacyjnego typu UNIX, oferowany wiersz poleceń jest bardziej złożony niż to konieczne i może zawieść:

lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)

W co najmniej jednym starym systemie UNIX lsofargument +r 1m%snie działa (nawet w przypadku administratora):

lsof: can't read kernel name list.

m%sJest specyfikacja formatu wyjściowego. Prostszy postprocesor tego nie wymaga. Na przykład następujące polecenie czeka na PID 5959 do pięciu sekund:

lsof -p 5959 +r 1 | awk '/^=/ { if (T++ >= 5) { exit 1 } }'

W tym przykładzie, jeśli PID 5959 wychodzi z własnej woli przed upływem pięciu sekund, ${?}jest 0. Jeśli nie, ${?}powróci 1po pięciu sekundach.

Może to być również warto wyraźnie zauważyć, że w +r 1The 1jest interwał sondowania (w sekundach), więc może być zmieniona odpowiednio do sytuacji.

kbulgrien
źródło