В bash я заметил, что если команда, использующая перенаправление, потерпит неудачу, любые программы, которые выполняются до этого, не запускаются.
Например, эта программа открывает файл «а» и записывает 50 байтов в файл «а». Однако выполнение этой команды с перенаправлением в файл с недостаточными разрешениями (~ root / log) не приводит к изменению размера файла «a».
$ ./write_file.py >> ~root/log
-bash: /var/root/log: Permission denied
cdal at Mac in ~/experimental/unix_write
$ ls -lt
total 16
-rw-rw-r-- 1 cdal staff 0 Apr 27 08:54 a <-- SHOULD BE 50 BYTES
Можно было бы подумать, что программа запустится, перехватит любой вывод (но также запишет в файл «a»), а затем не сможет записать любой вывод в ~ root / log. Вместо этого программа никогда не запускается.
Почему это так, и как bash выбирает порядок «проверок», которые он выполняет перед выполнением программы? Другие проверки также выполняются?
ps Я пытаюсь определить, действительно ли программа, запущенная под cron, запускалась при перенаправлении в файл «запрещен доступ».
источник
stdout
чтобы сделать именно это. Таким образом, вы не увидите никакого вывода, даже если ваша программа работала.write_file.py
программу и отправьте ее вывод~root/log
bash:« Извините, но вы не можете записывать в этот файл! »Оболочка делает именно то, что должна делать. Если она не может сделать то, что вы просили Это немедленно сообщает вам, почему возникает проблема, и дает вам возможность решить, как ее решить. Для всех, кто поддерживает bash, очень плохие вещи могут произойти, если вы запустите эту команду и не сохраните вывод. Если бы это было достаточно важным вы обозначили место , чтобы сохранить его, было бы неправильно ASS | U | ME это было нормально работать без сохранения STDOUT.Ответы:
На самом деле это не вопрос упорядочивания чеков, а просто порядок, в котором оболочка все настраивает. Перенаправления устанавливаются до запуска команды; так что в вашем примере оболочка пытается открыть
~root/log
для добавления, прежде чем пытаться сделать что-либо с участием./write_file.py
. Поскольку файл журнала не может быть открыт, перенаправление завершается неудачно, и оболочка прекращает обработку командной строки в этой точке.Один из способов продемонстрировать это - взять неисполняемый файл и попытаться запустить его:
Это показывает, что оболочка даже не смотрит,
./demo
когда перенаправление не может быть установлено.источник
Со страницы руководства bash, раздел REDIRECTION (выделено мной):
Таким образом, оболочка пытается открыть целевой файл, для
stdout
которого не удается, и команда не выполняется вообще.источник
Стоит заметить, что оболочка должна установить перенаправление перед запуском программы.
Рассмотрим ваш пример:
Что происходит в оболочке:
fork()
; дочерний процесс наследует дескрипторы открытого файла от своего родителя (оболочки).fopen()
(расширение) "~ root / log", иdup2()
это до fd 1 (иclose()
временный fd). Если произошелfopen()
сбой, позвоните,exit()
чтобы сообщить об ошибке родителю.exec()
"./write_file.py". Теперь этот процесс больше не выполняет какой-либо из наших кодов (если мы не выполнили его, и в этом случае мыexit()
должны сообщить об ошибке родителю).wait()
для ребенка завершать работу и обрабатывать свой код выхода (по$?
крайней мере, копируя его ).Таким образом, перенаправление должно происходить в дочернем элементе между
fork()
иexec()
: это не может происходить раньше,fork()
потому что оно не должно изменять стандартный вывод оболочки, и не может происходить послеexec()
того, как имя файла и исполняемый код оболочки теперь заменены программой Python. , Родитель не имеет доступа к файловым дескрипторам дочернего элемента (и даже если он это сделал, он не может гарантировать перенаправление междуexec()
и первой записью в стандартный вывод).источник
Мне жаль сообщать вам, что это совсем наоборот. Оболочка должна сначала открыть свой ввод-вывод, а затем передать управление программе.
tee
может оказаться полезным в этом случае:./write_file.py | tee -a ~root/log > /dev/null
источник