перенаправление вывода дескриптор файла
Мне нужно иметь возможность перенаправить вывод в файл, а также проверить код возврата скрипта в 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
выйти.