Zakończenie skryptu powłoki bash działającego w tle

16

Często używam bashskryptów powłoki do uruchamiania prostych poleceń dla wielu różnych plików. Na przykład załóżmy, że mam następujący bashskrypt o nazwie script.sh, która uruchamia program / komendę foona trzy pliki tekstowe "a.txt", "b.txt", "c.txt":

#!/bin/bash

for strname in "a" "b" "c"
do
foo $strname".txt"
done

Załóżmy również, że foo $strname".txt"jest to powolne, więc wykonanie skryptu zajmie dużo czasu (na przykład godziny lub dni). Z tego powodu chciałbym użyć, nohupaby wykonanie było kontynuowane, nawet jeśli terminal jest zamknięty lub odłączony. Chciałbym również, aby skrypt natychmiast przeszedł w tło, więc użyję &operatora. Dlatego użyję następującego polecenia do wywołania script.sh:

nohup bash script.sh &

Działa to dobrze w przypadku uruchamiania skryptu w tle i bez rozłączania, ale teraz załóżmy, że z jakiegoś powodu chciałbym zakończyć wykonywanie w pewnym momencie. W jaki sposób mogę to zrobić?

Problem, który napotkałem, polega na tym, że patrząc na topto widzę tylko fooodpowiadające "a.txt". Mogę zakończyć to foopołączenie, ale następnie zostaje wywołane fooodpowiadające mu polecenie, "b.txt"a następnie muszę je również zakończyć i tak dalej. W przypadku dziesiątek lub setek plików tekstowych określonych w forpętli przerywanie każdego z foonich staje się trudne ! Więc jakoś muszę zamiast zakończyć skrypt sam , a nie poszczególne połączenia wydane ze skryptu powłoki.

Kiedy wpisuję polecenie

ps -u myusername

gdzie myusernamejest moja nazwa użytkownika, otrzymuję listę uruchomionych procesów. Ale widzę dwa różne identyfikatory procesów o nazwie bash. Skąd mam wiedzieć, który z tych procesów, jeśli w ogóle, odpowiada mojemu pierwotnemu wezwaniu nohup bash script.sh &?

Andrzej
źródło
@Andrew, czy oba te procesy pokazują nohup wspomniane w poleceniu? .... alternatywnie możesz wypróbować ps -aWu Andrew i sprawdzić, czy znajdziesz lokalizację pojedynczego długiego wpisu bez nohup .... czy to pomaga?
nitin
2
Na marginesie, twoje cytaty są zwariowane. for s in a b c; do foo "$s".txt; done
tripleee
1
@NSD: Nie, nohupminie dużo czasu, zanim pojawi się lista procesów, aby zobaczyć rozpoczęte zadanie. Możesz spojrzeć na kolumnę „nicość” w danych pswyjściowych, ale odpowiedzi tutaj są bardziej przydatne.
tripleee

Odpowiedzi:

10

Domyślnie psnie wyświetla parametrów, z którymi program został wywołany. Opcje -fi -loba pokażą pełne połączenie.

ps -fu username

spowoduje wyjście, które wygląda następująco:

username 23464 66.7  0.0  11400   628 pts/5    R    15:28   1:40 bash script.sh
j883376
źródło
2
Jest to umiarkowanie użyteczne, ale nie ujednoznacznia wielu procesów z tymi samymi argumentami.
tripleee
11

Masz kilka opcji. Ponieważ proces działa w tle, możesz jobsgo znaleźć:

nohup bash script.sh &
...
jobs
[1]+ Running    nohup bash script.sh &
kill %1
jobs
[1]+ Terminated nohup bash script.sh &

Możesz także użyć pkilldo przeszukiwania tabeli procesów w celu dopasowania wiersza poleceń; mianowicie:

pkill -f script.sh
JRFerguson
źródło
1

Dane pswyjściowe (np. ps aux) Obejmują identyfikator procesu rodzica. Zabij rodzica bash, a jego dzieci również zostaną rozwiązane.

Aby uzyskać wizualizację drzewa procesów ASCII, spróbuj pstree -puruchomić kilka procesów w tle.

potrójny
źródło