Czy mogę w jakiś sposób dodać „&& prog2” do już uruchomionego prog1?


87

Większość powłok zapewnia funkcje takie jak &&i ;do łączenia wykonywania poleceń w określony sposób. Ale co, jeśli polecenie jest już uruchomione, czy nadal mogę w jakiś sposób dodać kolejne polecenie do wykonania w zależności od wyniku pierwszego?

Powiedz, że pobiegłem

$ /bin/myprog
some output...

ale naprawdę chciałem /bin/myprog && /usr/bin/mycleanup. Nie mogę zabić myprogi zrestartować wszystkiego, ponieważ straciłoby to zbyt wiele czasu. Mogę Ctrl+ Zto i fg/ bgjeśli to konieczne. Czy to pozwala mi połączyć w jedno polecenie?

Najbardziej interesuje mnie bash, ale odpowiedzi na wszystkie popularne powłoki są mile widziane!

Odpowiedzi:


118

Powinieneś być w stanie to zrobić w tej samej powłoce, w której znajduje się waitpolecenie:

$ sleep 30 &
[1] 17440

$ wait 17440 && echo hi

...30 seconds later...
[1]+  Done                    sleep 30
hi

fragment strony podręcznika użytkownika Bash

wait [n ...]
     Wait for each specified process and return its termination status. Each n 
     may be a process ID or a job specification; if a job spec is given,  all 
     processes  in that job's pipeline are waited for.  If n is not given, all 
     currently active child processes are waited for, and the return status is 
     zero.  If n specifies a non-existent process or job, the return status is 
     127.  Otherwise, the return status is the exit status of the last process 
     or job waited for.

Oczekiwanie na polecenie powinno wykonać zadanie.
BillThor,

Istnieje szereg krótkich form do wprowadzania PID z procesu będącego w tle, takie jak %, %1i $!. Ważne jest, aby podać PID, w przeciwnym razie zawsze uruchomi się drugie polecenie.
BillThor,

@BillThor - czy kwalifikujesz odpowiedź, czy mi to mówisz?
slm

Kwalifikuję odpowiedź. Zwykły waitnie zapewni pożądanego rezultatu. Często używa się krótkich formularzy, ponieważ są one mniej podatne na literówki.
BillThor,

2
Pozwól mi być pierwszym, który pogratuluje ci błyszczącej nowej odznaki :)
terdon

63

fgzwraca kod zakończenia programu, który wznawia. Możesz zatem zawiesić swój program, ^Za następnie użyć go, fg && ...aby go wznowić.

$ /bin/myprog
some output...
^Z
[1]+ Stopped              /bin/myprog
$ fg && /usr/bin/mycleanup

jeśli ponownie zawiesisz, zanim się skończy i zrobisz to samo za pomocą innego polecenia, czy początkowe tworzenie łańcucha mycleanup zostanie zastąpione?
Burhan Ali,

3
@ BurhanAli Zawieszenie myprogpo raz drugi powoduje fgzakończenie z kodem wyjścia 20 - który jest niezerowy, więc łańcuchowe mycleanuppolecenie nie jest wykonywane.
n.

1

Nie jestem pewien, czy to, o co prosisz, jest możliwe, ale jeśli nadal masz powłokę, z której uruchomiłeś program, zawsze możesz sprawdzić $?status wyjścia ostatniego procesu:

$ /bin/myprog
some output...
$ if [ $? -ne 0 ];then echo "non-zero exit status";else echo "0 exit status";fi

1
To zadziała, ale będzie musiał uruchomić to później ręcznie, chce uruchomić to automatycznie po zakończeniu polecenia.
slm

@slm Zgoda. Nie mam rozwiązania tego konkretnego problemu.
Joseph R.

3
Sprawdź waitpolecenie w Bash.
slm

1

Jeśli zadanie znajduje się na pierwszym planie, każde z tych poleceń będzie miało takie samo zachowanie, jak się spodziewasz.

[ $? -eq 0 ] && prog2
(( $? )) || prog2

UWAGA: $? będzie zawierać status powrotu uruchomionego programu po jego wyjściu.

To wyraźnie wskazuje, co zrobiłaby powłoka, gdybyś pierwotnie wprowadził polecenie.

prog1 && prog2

Jeśli pierwsze polecenie nie odczytuje stdini działa na pierwszym planie, nowe polecenie można wprowadzić podczas działania pierwszego polecenia. Powłoka odczyta ją i wykona po wykonaniu pierwszego polecenia. Jeśli polecenie będzie działać w tle, jest mało prawdopodobne, że będzie czytać stdin.

EDYCJA: WAITMożna także użyć zadania w tle i użyć polecenia. Należy to zrobić ostrożnie, jeśli w tle uruchomiono także inne zadania. Specyfikacja zadania jest wymagana, aby WAITpolecenie zwracało status zadania oczekującego.


To zadziała, ale będzie musiał uruchomić to później ręcznie, chce uruchomić to automatycznie po zakończeniu polecenia.
slm

4
@slm Dopóki polecenie nie odczytuje standardowego wejścia, nowe polecenie można wprowadzić podczas działania pierwszego polecenia. Powłoka przeczyta ją, gdy tylko zostanie wykonane pierwsze polecenie.
BillThor

Jeśli cokolwiek zrobi w skorupce po tym, jak zostanie w tle, prawdopodobnie zostanie ukryty. Przynajmniej zgodnie z przedmową. testy, które robiłem do tej pory!
slm

2
@BillThor Myślę, że powinieneś dodać ten komentarz do swojej odpowiedzi.
Joseph R.

2
Tak, używanie też waitnie jest idealne. Zaletą IMO jest to, że daje nam wyraźniejszy interfejs API, z którym mamy do czynienia. Wpisywanie większej liczby poleceń w wierszu poleceń po uruchomieniu czegoś wydawało mi się trochę nieprzyzwoite. waitnadal cierpi z powodu braku bezpośredniego łącza do działającego PID, wrt status powrotu. Wydaje się, że jest to problem bardziej związany z tym, jak Bash implementuje różne rzeczy: stackoverflow.com/questions/356100/… . Może to być tak dobre, jak to możliwe.
slm
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.