перенаправление вывода дескриптор файла
Мне нужно иметь возможность перенаправить вывод в файл, а также проверить код возврата скрипта в KSH (не могу использовать pipestatus или pipefail), я нашел решение, но я не уверен, что значение file discriptor 4, может кто-нибудь объяснить, пожалуйста?
{
rc=$(
{
{
. somescript.sh 2>&1
echo "$?" >&3
} | tee -a somefile.txt
} 3>&1 >&4 4>&-
)
} 4>&1
echo "${rc}"
2 ответа:
rc=$(...)означает, что код возврата будет тем, что напечатано на файловом дескрипторе (fd)1кодом внутри(...). Итак, каким-то образом то, чтоsomescript.shвыводит, должно быть перемещено из fd1и затем возвращено позже. Строкаechoвыводит код возвратаsomescript.shв fd3. Затем3>&1отправляет сохраненный код возврата в fd1, где$(...)ожидает его. Однако это означает, что старому fd1(от{somescript 2>&1 } | tee) некуда идти. Таким образом, старый fd1перенаправляется на fd4С>&4(и входная сторона закрывается с помощью4>&-, так как она не будет использоваться). Затем, как только$(...)заканчивается,4>&1в конце помещает выходные данныеsomescript|teeобратно в fd1, где другие программы ожидают его.Фу!
Без
>&4Выходsomescript.shи выходecho "$?"были бы смешаны на fd1из-за3>&1. Таким образом, fd4является удерживающим пером для фактического выводаsomescript.shв течение того времени, когда fd1используется для переноса кода возврата.
Если вы хотите использовать именованный канал, вы можете обойтись без всех пререканий с файловыми дескрипторами:
mkfifo p tee -a somefile.txt < p & . somescript.sh > p rc=$?Здесь мы запускаем
teeв фоновом режиме, позволяя ему считывать входные данные из именованного каналаp. После запуска этого задания мы создаем исходный код сценария и перенаправляем его выходные данные в именованный канал. После завершения работы скрипта его состояние выхода можно сохранить вrcс помощью обычного оператора присваивания. Это также закроет конец оболочки трубы, что приведет к тому, что другой конец закроется как ну и позвольтеteeвыйти.