GNU/Linux >> Znalost Linux >  >> Linux

proč se smyčka bash while neukončí při napojení na ukončený dílčí příkaz?

Je to kvůli výběru při implementaci.

Spuštění stejného skriptu na Solaris s ksh93 vytváří jiné chování:

$ while /usr/bin/true ; do echo "ok" | cat ; done | exit 1
cat: write error [Broken pipe]

Problém spouští vnitřní kanál, bez něj smyčka opustí jakýkoli shell/OS:

$ while /usr/bin/true ; do echo "ok" ; done | exit 1
$

cat dostává signál SIGPIPE pod bash, ale shell stejně iteruje smyčku.

Process 5659 suspended
[pid 28801] execve("/bin/cat", ["cat"], [/* 63 vars */]) = 0
[pid 28801] --- SIGPIPE (Broken pipe) @ 0 (0) ---
Process 5659 resumed
Process 28801 detached
Process 28800 detached
--- SIGCHLD (Child exited) @ 0 (0) ---
Process 28802 attached
Process 28803 attached
[pid 28803] execve("/bin/cat", ["cat"], [/* 63 vars */]) = 0
Process 5659 suspended
[pid 28803] --- SIGPIPE (Broken pipe) @ 0 (0) ---
Process 5659 resumed
Process 28803 detached
Process 28802 detached
--- SIGCHLD (Child exited) @ 0 (0) ---
Process 28804 attached
Process 28805 attached (waiting for parent)
Process 28805 resumed (parent 5659 ready)
Process 5659 suspended
[pid 28805] execve("/bin/cat", ["cat"], [/* 63 vars */]) = 0
[pid 28805] --- SIGPIPE (Broken pipe) @ 0 (0) ---
Process 5659 resumed
Process 28805 detached
Process 28804 detached
--- SIGCHLD (Child exited) @ 0 (0) ---

Bash dokumentace uvádí:

Shell čeká na všechny příkazy v kanálu k ukončení před vrácením hodnoty.

Ksh dokumentace uvádí:

Každý příkaz, možná kromě posledního, je spuštěn jako samostatný proces; shell čeká na poslední příkaz ukončit.

POSIX uvádí:

Pokud potrubí není na pozadí (viz Asynchronní seznamy), shell bude čekat na poslední příkaz zadaný v kanálu k dokončení a může také čekat na všechny příkazy dokončit.


Tento problém mě trápí roky. Díky jilliagre za popostrčení správným směrem.

Trochu zopakuji otázku, na mém linuxovém boxu to skončí podle očekávání:

while true ; do echo "ok"; done | head

Ale když přidám dýmku, není ukončit podle očekávání:

while true ; do echo "ok" | cat; done | head

To mě roky frustrovalo. Zvážením odpovědi napsané od jilliagre jsem přišel s touto úžasnou opravou:

while true ; do echo "ok" | cat || exit; done | head

Q.E.D. ...

No, ne tak docela. Zde je něco trochu složitějšího:

i=0
while true; do
    i=`expr $i + 1`
    echo "$i" | grep '0$' || exit
done | head

Tohle nefunguje správně. Přidal jsem || exit takže ví, jak předčasně ukončit, ale úplně první echo neodpovídá grep takže smyčka okamžitě skončí. V tomto případě vás opravdu nezajímá stav ukončení grep . Moje řešení je přidat další cat . Zde je tedy vytvořený skript nazvaný "desítky":

#!/bin/bash
i=0
while true; do
    i=`expr $i + 1`
    echo "$i" | grep '0$' | cat || exit
done

To se správně ukončí při spuštění jako tens | head . Díky Bohu.


Linux
  1. Proč je Bash Prompt odposloucháván, když procházím historii?

  2. Výchozí kód ukončení při ukončení procesu?

  3. Proč se skript Bash po spuštění neukončí?

  1. Udržujeme vás ve smyčce – příklady opakování pro, Zatímco, dokud

  2. Jak získat stav ukončení smyčky v bash

  3. Bash:Smyčka, dokud se stav ukončení příkazu nerovná 0

  1. Skriptování v Linuxu:3 postupy pro smyčky while v Bash

  2. Proč Bash `(())` nefunguje uvnitř `[[]]`?

  3. Proč je vfork() určeno k použití, když podřízený proces volá exec() nebo exit() ihned po vytvoření?