Почему мой скрипт не выполняется, когда просыпаешься из systemd suspension?

Вы можете использовать here-doc и . source для эффективной, дружественной POSIX модели общего коллектора.

. 8<<-\IOHERE /proc/self/fd/8

command
… 
fn() { declaration ; } <<WHATEVER
# though a nested heredoc might be finicky
# about stdin depending on shell
WHATEVER
cat -u ./stdout | ./works.as >> expect.ed
IOHERE

Когда вы открываете heredoc, вы сигнализируете оболочке с помощью входного маркера IOHERE, что она должна перенаправить свой вход в указанный вами файл-дескриптор, пока не встретит другой конец вашего маркера-ограничителя. Я посмотрел вокруг, но не увидел много примеров использования номера fd перенаправления, как я показал выше, в сочетании с оператором heredoc, хотя его использование четко указано в руководстве по базовым shell-командам POSIX. Большинство людей просто указывают его на stdin и стреляют, но я обнаружил, что создание скриптов таким образом позволяет сохранить stdin свободным, а входящие в состав приложения не жалуются на заблокированные пути ввода/вывода.

Содержимое heredoc транслируется в указанный вами дескриптор файла, который, в свою очередь, интерпретируется как shell-код и выполняется встроенной командой ., но не без указания конкретного пути для ... Если путь /proc/self вызывает у вас проблемы, попробуйте /dev/fd/n или /proc/$$. Этот же метод, кстати, работает и с трубами:

cat ./*.sh | . /dev/stdin

Вероятно, это по меньшей мере неразумно, чем кажется. Конечно, вы можете сделать то же самое с помощью sh, но цель . - выполнение в текущем окружении оболочки, что, вероятно, то, чего вы хотите, и, в зависимости от вашей оболочки, гораздо больше шансов работать с heredoc, чем со стандартной анонимной трубой.

В любом случае, как вы, вероятно, заметили, я все еще не ответил на ваш вопрос. Но если вы подумаете об этом, то точно так же, как heredoc передает весь ваш код в .'in, он также предоставляет вам единственную, простую, точку выхода:

. 5<<EOIN /dev/fd/5 |\ 
    tee -a ./log.file | cat -u >$(tty)
script
… 
more script
EOIN

Таким образом, весь терминальный stdout любого кода, выполняемого в вашем heredoc, выводится из . как само собой разумеющееся и может быть легко перерезан из одной трубы. Я включил вызов cat без буферизации, потому что мне неясно текущее направление stdout, но это, вероятно, излишне (почти наверняка так оно и есть в любом случае), и трубопровод, вероятно, может закончиться прямо на tee.

Вы также можете усомниться в отсутствии кавычек обратной косой черты во втором примере. Эту часть важно понять до того, как вы приступите к работе, и она может дать вам несколько идей о том, как ее можно использовать. Ограничитель heredoc, заключенный в кавычки (до сих пор мы использовали IOHERE и EOIN, причем первый я заключил в кавычки с обратным слешем, хотя "одинарные" или "двойные" кавычки могли бы служить той же цели), запретит оболочке выполнять любое расширение параметров содержимого, но ограничитель без кавычек оставит содержимое открытым для расширения. Последствия этого, когда ваш heredoc является . sourced, драматичны:

. 3<<HD ${fdpath}/3
: \${vars=$(printf '${var%s=$((%s*2))},' `seq 1 100`)} 
HD
echo $vars
> 4,8,12… 
echo $var1 $var51
> 4 104

Поскольку я не процитировал ограничитель heredoc, оболочка расширила его содержимое по мере считывания и перед тем, как передать полученный файловый дескриптор в . для выполнения. Это привело к тому, что команды были разобраны дважды - во всяком случае, расширяемые команды. Поскольку я заключил в обратную косую черту расширение параметра $vars, оболочка игнорировала его объявление при первом проходе и только удаляла обратную косую черту, чтобы все расширенное содержимое printf могло быть оценено нулем, когда . подставлял скрипт при втором проходе.

Эта функциональность в точности соответствует тому, что может обеспечить опасный встроенный модуль оболочки eval, даже если цитирование гораздо проще обработать в heredoc, чем в eval, и оно может быть столь же опасным. Если вы не планируете это тщательно, то, вероятно, лучше кавычки ограничителя "EOF" сделать по привычке. Просто говорю.

EDIT: Эх, я оглядываюсь назад и думаю, что это слишком большая натяжка. Если ВСЕ, что вам нужно сделать, это объединить несколько выходов в одну трубу, то самый простой метод - это использовать a:

{ or ( command ) list ; } | tee -a ea.sy >>pea.sy

Курсивы будут пытаться запустить содержимое в текущей оболочке, в то время как парены будут выводить содержимое автоматически. Тем не менее, любой может сказать вам это, и, по крайней мере, на мой взгляд, решение . heredoc является гораздо более ценной информацией, особенно если вы хотите понять, как на самом деле работает оболочка.

Удачи!

0
03.12.2018, 14:21
1 ответ

Я столкнулся с той же ошибкой. Вики arch linux в настоящее время неверна в отношении того, куда поместить скрипт. Вам нужно поместить скрипт в /lib/systemd/system-sleep/вместо /usr/lib/systemd/system-sleep/.

См. такжеman systemd-suspend.service:

Immediately before entering system suspend and/or hibernation systemd-suspend.service (and the other mentioned units, respectively) will run all executables in /lib/systemd/system-sleep/ and pass two arguments to them.

2
28.01.2020, 02:41

Теги

Похожие вопросы