Perché la funzione non torna fino al termine del processo in background?


21

Considera questo script:

#!/bin/bash
function start {
  leafpad &
  echo $!
}
PID=$(start)
echo "PID is $PID"

Lo script non continua oltre la parentesi graffa di chiusura fino al termine del processo leafpad, anche se si tratta di un processo in background.

Perchè è questo? È possibile avviare un processo in background da una funzione?

Risposte:


22

La funzione ritorna, ma il comando di sostituzione dei blocchi si blocca, perché hai creato un lavoro in background, ma hai ancora aperto lo stdout fd. Basta chiuderlo aggiungendo >/dev/nullprima di &.

#!/bin/bash
function start {
  leafpad >/dev/null &
  echo $!
}
PID=$(start)
echo "PID is $PID"

Se vuoi che il tuo processo abbia anche chiuso stdin, stdout, stderr, usa questo:

leafpad >/dev/null 0>&1 2>&1 &

Questo chiuderà stdin (0), stdout (1) e stderr (2), quindi sfondo (&). Inoltre, quando si utilizzano questi reindirizzamenti di stream , non dimenticare che sono "duplicati", ciò significa duplicati nell'ordine di esecuzione.

1>/dev/null 2>&1

e

2>&1 1>/dev/null

non sono gli stessi! Nel primo, stai duplicando uno stream su / dev / null (che è quello che vuoi), nel secondo, stai duplicando / dev / stdout su stderr, quindi chiudi stdout. Quindi qualsiasi messaggio inviato stderrapparirà nella tua console.


Confermato sul mio sistema
user120161

10
Non stai chiudendo i flussi, li stai reindirizzando.
dcat,

4
chiudere; n>&-dove si ntrova il descrittore di file.
dcat,

1
@cat: Sì, ma il reindirizzamento a / da /dev/nullnon porterà a errori di I / O quando un processo tenta di scrivere il suo stdout, ma trova che 1è un FD non valido. Quindi la terminologia nel post è sbagliata, non l'attuale programmazione bash. (In realtà, la duplicazione di FD da 1 a 0 significa che stdin sarà un descrittore di file aperto con O_RDONLY, il che probabilmente darà un errore (piuttosto che il no-byte desiderato disponibile) quando il processo tenta di leggere.) Eg wc >/dev/null 0>&1->wc: standard input: Bad file descriptor
Peter Cordes,

1
@PeterCordes - La chiusura del vecchio descrittore e il reindirizzamento di quello nuovo non devono necessariamente escludersi a vicenda. exec <&- >&- <>/dev/null >&0gestisce lo stdin / out piuttosto esaurientemente. Fa zshalmeno una differenza , che consentirà di concatenare tutte le aperture sullo stesso descrittore automaticamente quando è impostato multios.
Mikeserv,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.