Функция возвращается, но подстановка команды блокируется, потому что вы создали фоновое задание, но у вас все еще открыт stdout fd. Просто закройте его, добавив >/dev/null
перед &
.
#!/bin/bash
function start {
leafpad >/dev/null &
echo $!
}
PID=$(start)
echo "PID is $PID"
Если вы хотите, чтобы у вашего процесса были также закрыты stdin, stdout, stderr, используйте это:
leafpad >/dev/null 0>&1 2>&1 &
Это закроет stdin (0), stdout (1) и stderr (2), затем background (&). Кроме того, при использовании этих потоковых перенаправлений не забывайте, что они «дублированы», то есть дублируются в порядке выполнения.
1>/dev/null 2>&1
а также
2>&1 1>/dev/null
не то же самое! В первом случае вы дублируете поток в / dev / null (что вам и нужно), во втором вы дублируете / dev / stdout в stderr, а затем закрываете stdout. Таким образом, любое отправленное сообщение stderr
появится в вашей консоли.
n>&-
гдеn
дескриптор файла./dev/null
не приведет к ошибкам ввода-вывода, когда процесс попытается записать свой стандартный вывод, но обнаружит, что1
это недопустимый FD. Так что терминология в посте неверна, а не фактическое программирование на bash. (На самом деле, дублирование FD с 1 по 0 означает, что stdin будет дескриптором файла, сO_RDONLY
которым открывается файл , что, вероятно, приведет к ошибке (а не к желаемому отсутствию байтов), когда процесс попытается прочитать.) Например,wc >/dev/null 0>&1
->wc: standard input: Bad file descriptor
exec <&- >&- <>/dev/null >&0
обрабатывает stdin / out довольно исчерпывающе. Это имеет значениеzsh
по крайней мере в том, что будет сортировать все открытия по одному и тому же дескриптору автоматически, когда установлено multios.