Jak uruchomić wiele poleceń, które mają & w jednym wierszu poleceń?

12

Wystąpił problem z bólem głowy.

Chcę wykonywać wiele poleceń w tle, więc chcę je uruchamiać pojedynczo. Łatwo jest uruchomić jedno polecenie w powłoce linux w tle, podobnie jak to:

myCommand &

Łatwo jest również uruchomić wiele poleceń, tak jak poniżej:

myCommand1 && myCommand2

lub

myCommand1 ; myCommand2

Ale jeśli chcę uruchomić wiele poleceń w tle, próbowałem następującego formatu poleceń, ale nie powiodło się:

myCommand1 & && myCommand2 &

lub

myCommand1 & ; myCommand2 &

Oba formaty zawodzą. Jak mogę uruchomić wiele poleceń, które mają &jeden wiersz poleceń?

Zegar ZHONG
źródło
2
Umieść je w skrypcie i uruchom skrypt w tle
Panther
Panther, wydaje się, że użycie () może rozwiązać ten problem znacznie łatwiej niż użycie skryptu. Spróbujmy najpierw w pełni wykorzystać funkcje dostarczone przez samą powłokę, zamiast tworzyć to, co sami chcemy. Ale oczywiście użycie skryptu może również rozwiązać ten problem. W każdym razie dzięki.
Zegar ZHONG
Co jeśli chcę uruchomić „tail -F <file1>> <file2>”, a następnie „jobs -l”, po czym ponownie następuje „disown -h% 1”
akskap 30.04.18

Odpowiedzi:

24

Posługiwać się ().

Jeśli chcesz je uruchamiać sekwencyjnie:

(myCommand1; myCommand2) &

lub

(myCommand1 &) && (myCommand2 &)

Jeśli chcesz, aby działały równolegle:

myCommand1 & myCommand2 &

W bash możesz także użyć tego (spacja za {i; są obowiązkowe):

{ myCommand1 && myCommand2; } &
Rinzwind
źródło
3
(myCommand1 &) && (myCommand2 &)będzie działać, myCommand2nawet jeśli się myCommand1nie powiedzie.
terdon
() może pomóc bashowi rozróżnić & i &&. Więc po prostu użyj (), aby oddzielić jednostkę wykonawczą, gdy chcemy użyć zbierania & i &&.
Zegar ZHONG
16

Przypuszczam, że chcesz tego:

myCommand1 & myCommand2 &

Spowoduje myCommand1to uruchomienie i wysłanie go w tło, po którym następuje znak ampersand, a następnie natychmiast rozpocznie się myCommand2i wyśle ​​to również w tło, tym samym ponownie uwalniając powłokę.

Listy

Dla lepszego zrozumienia można zastąpić rurociągu przez polecenia tutaj.

Lista jest sekwencją jednego lub więcej potoków oddzielonych przez jednego z operatorów ; , & , && lub lub || i opcjonalnie zakończone jednym z ; , i lub lub .

Jeśli polecenie zostanie zakończone przez operatora sterującego & , powłoka wykonuje polecenie w tle w podpowłoce. Powłoka nie czeka na zakończenie polecenia, a zwracanym statusem jest 0. Polecenia oddzielone znakiem a ; są wykonywane sekwencyjnie; powłoka czeka na zakończenie każdego polecenia. Status powrotu to status wyjścia ostatniego wykonanego polecenia.

Listy AND i OR to sekwencje jednego lub więcej potoków oddzielone znakami && i || odpowiednio operatorzy sterujący.
Źródło:man bash

Podzielmy to na przykłady. Możesz zbudować listę, łącząc polecenia i oddzielając je jednym z poniższych ; & && ||:

command1 ; command2  # runs sequentially
command1 && command2 # runs sequentially, runs command2 only if command1 succeeds
command1 || command2 # runs sequentially, runs command2 only if command1 fails
command1 & command2  # runs simultaneously

Można zakończyć list jednego z nich: ; & <newline>.
Zwykle wykonuje się polecenie lub listę, naciskając klawisz Enter, który jest równy <newline>. Średnik ;służy temu samemu celowi, szczególnie w skryptach. Ampersand &uruchamia jednak polecenia w podpowłoce w tle, natychmiast uwalniając powłokę.

Możesz używać okrągłych ()lub nawiasów klamrowych {}do dalszych list grup, z tą różnicą, że okrągłe nawiasy odradzają podpowłokę, a nawiasy kręcone nie. Nawiasy klamrowe wymagają spacji po pierwszej i średnika lub nowej linii przed nawiasem zamykającym. Na przykład:

# if c1 succeeds start a shell in the background
# and run c2 and c3 sequentially inside it
c1 && ( c2 ; c3 ) & 
# run c1 and if it succeeds c2 sequentially as a group command
# if c1 or c2 fail run c3 in the background
{ c1 && c2 ;} || c3 &

Może to być dość skomplikowane, jeśli nie masz pewności co do użycia truei falsesprawdzenia, czy konstrukcja działa zgodnie z oczekiwaniami:

$ { true && true ;} || echo 2
$ { true && false ;} || echo 2
2

Kontrola pracy

Na jobspolecenie wyświetla listę zadań, które są uruchomione w tle lub zostały niedawno ukończony w bieżącej powłoki. Istnieje wiele skrótów klawiaturowych i poleceń do kontroli zadań:

  • Ctrl+ Zwpisuje znak zawieszenia, który powoduje zatrzymanie procesu aktualnie działającego na pierwszym planie, nie jest on zakończony, ale pozostaje na jobsliście
  • Ctrl+ Ywpisuje znak opóźnionego zawieszenia, który powoduje zatrzymanie procesu aktualnie działającego na pierwszym planie, gdy próbuje on odczytać dane wejściowe z terminala
  • fg= %przenosi proces na pierwszy plan, uruchamiając go w razie potrzeby, możesz określić proces w następujący sposób:

     %       # last process in the jobs list
     %1      # 1st process in the jobs list
     %abc    # process beginning with the string “abc”
     %?abc   # process containing the string “abc” anywhere
  • bg= %&przenosi proces w tło, uruchamiając go w razie potrzeby:

     %&      # last process in the jobs list
     %1&     # 1st process in the jobs list
     %abc&   # process beginning with the string “abc”
     %?abc&  # process containing the string “abc” anywhere
  • wait oczekuje na zakończenie procesu w tle i zwraca status zakończenia:

     wait %1 # 1st process in the jobs list

    Wyobraź sobie, że rozpocząłeś długi proces ( jobsujawnia swój numer 3), a potem zdałeś sobie sprawę, że chcesz, aby komputer został zawieszony po zakończeniu, a echotakże komunikat, jeśli proces się nie powiedzie:

     wait %3 || echo failed ; systemctl suspend
deser
źródło
Ale ważne, aby uważać na &&, zależy to od tego, co komenda zwraca , więc musimy być pewni, że to, co nazywamy, faktycznie zwraca coś, co bash uważa za prawdziwą wartość…?
mathreadler
@mathreadler O ile nie mówisz o źle wykonanym skrypcie użytkownika, wartość wyjściowa jest bardzo dobrze zdefiniowana (patrz man bash) i szeroko używana dokładnie tak, jak powinna AFAIK - nigdy nie doświadczyłem nic dziwnego.
deser
dokładnie należy uważać na źle wykonane skrypty użytkownika. Istnieją i mogą być kłopotem ze znalezieniem takich błędów. Askubuntu nie pozwala mi na „@ deser” ciebie.
mathreadler
Ach, dobrze, to ma sens teraz, kiedy o tym wspominasz.
mathreadler