La fonction renvoie, mais la substitution de commandes bloque, car vous avez créé un travail en arrière-plan, mais votre stdout fd est toujours ouvert. Fermez-le simplement en ajoutant >/dev/null
avant le &
.
#!/bin/bash
function start {
leafpad >/dev/null &
echo $!
}
PID=$(start)
echo "PID is $PID"
Si vous souhaitez que votre processus ait également stdin, stdout, stderr fermé, utilisez ceci:
leafpad >/dev/null 0>&1 2>&1 &
Cela fermera stdin (0), stdout (1) et stderr (2), puis l'arrière-plan (&). De plus, lorsque vous utilisez ces redirections de flux, n'oubliez pas qu'elles sont "dupées", c'est-à-dire dupliquées dans l'ordre d'exécution.
1>/dev/null 2>&1
et
2>&1 1>/dev/null
ne sont pas les mêmes ! Dans le premier, vous dupliquez un flux vers / dev / null (ce que vous voulez), dans le second, vous dupliquez / dev / stdout vers stderr, puis fermez stdout. Ainsi, tout message envoyé à stderr
apparaîtra dans votre console.
n>&-
oùn
est le descripteur de fichier./dev/null
ne provoquera pas d'erreurs d' E / S lorsqu'un processus essaiera d'écrire sa sortie standard, mais trouvera qu'il1
s'agit d'un FD non valide. Donc, la terminologie dans le message est erronée, pas la programmation bash réelle. (En fait, la duplication de FD 1 à 0 signifie que stdin sera un descripteur de fichier ouvert avecO_RDONLY
, ce qui donnera probablement une erreur (plutôt que le nombre d'octets disponible disponible) lorsque le processus essaiera de lire.) Par exemplewc >/dev/null 0>&1
->wc: standard input: Bad file descriptor
exec <&- >&- <>/dev/null >&0
gère stdin / out assez exhaustivement. Cela fait une différence danszsh
au moins ce qui va concaténer toutes les ouvertures sur le même descripteur automatiquement lorsque multios est défini.