Я пытаюсь написать функцию, которую я вызываю logAction
специально для Ksh
, которая считывает входные данные из канала и принимает аргументы в одном вызове функции. Я пытаюсь отлаживать это в течение двух недель в Google и на таких сайтах.Написание функции оболочки, которая принимает входные данные из одного и того же канала и аргументы
Целью функции, которую я пытаюсь создать, является упрощение процесса регистрации вывода в файл журнала для других сценариев, которые я разработал. Я намерен использовать команду для различных ситуаций, но 2 проще всего описать и проиллюстрировать то, что я пытаюсь похожи на следующее:
Синтаксис Пример 1:
logAction 1 "Script executed some action."
Синтаксис Пример 2:
COMMAND1 | COMMAND2 | logAction 1
Как вы можете видеть, я хочу, чтобы иметь возможность передать информацию предполагаемого журнала функции либо в качестве аргумента или stdinput через трубу, чтобы захватить выходную последовательность команд. 3-й сценарий будет предварять текст перед централизованным выходом, т.е.
Синтаксиса Примером 3:
COMMAND1 | COMMAND2 | logAction 1 "This is the output: "
Выход ниже показывает, что результат будет использовать синтаксис в примере 3:
[2015/12/28 10:20:32] This is the output: <Output from COMMAND1 | COMMAND 2>
Вот базовый скелет функции, которую я пытаюсь создать.
function logAction {
while read -t 0 -u 0 stdinput
do
echo "StdInput:'$stdinput'"
pipedinput=$stdinput
done
pipedinput=${pipedinput:-}
case $1 in
1) #Output text only to log file
output=$(echo "$pretag ${@:2} $pipedinput")
echo $output >> $LOG
2) #Output text to screen and log file
output=$(echo "$pretag ${@:2} $pipedinput")
echo $output
echo $output >> $LOG
3)
....
esac
unset pipedinput
}
Изначально я не поставить -t
аргумент команды read
, а функция будет приостановить выполнение до тех пор, пока пользователь не вошел CTRL-D
указать EOF
. Однако для моих целей эта функция предназначена для бесшумной работы и не должна запрашивать ввод пользователя. Добавление аргумента -t 0
с помощью команды read
указывает команде чтения на тайм-аут с 0 секундами вместо ожидания EOF
с клавиатуры.
Это решение проблемы для некоторых случаев; Однако, команда read
не захватывает любой вход при использовании с cat
команды, как так:
cat somefile.txt | logAction 1
cat somefile.txt | awk '{ a=a" "$1 }END{ print a }' | logAction 1
Тем не менее, используя echo
, кажется, работает:
echo "ab bc cd de ef fg gh" | logAction 1 "This is the output: "
Я был в состоянии заставить его работать с cat
, изменив значение 0 для таймаута до 0,1 (то есть read -t 0.1
), но я обеспокоен тем, что это грязное решение. Это, по-видимому, указывает на состояние гонки, когда команда read
выполняется до того, как труба закончила свой вывод и закрылась. Это было не то, что я ожидал, так как я думал, что предыдущая команда в последовательности труб должна завершить выполнение до выполнения следующей команды.
Есть ли способ сообщить команде read
игнорировать stdin с клавиатуры и использовать стандартный вывод из предыдущей команды в трубе?Я попытался сказать ему использовать FD0
(который, как я думал, был выводом из трубы, но, похоже, также подключен к клавиатуре) с аргументом -u 0
, но это, похоже, не работает.
Спасибо за ваш ответ @Ziffusion. Кажется, это работает. Я использовал этот трюк, прежде чем использовать 'cat'; однако я не использовал его, потому что думал, что я где-то читаю, где это может столкнуться с состоянием гонки или иметь другие уязвимости. Кажется предпочтительным, чтобы была встроенная команда для этой функции против этой обманчивости с 'cat'. Тем не менее, я тестировал его с помощью своего кода и, похоже, сейчас работает. Мне все еще интересно, почему 'read' не работает в моем примере. Как получается, что оболочка выполняет параметр 'read' timeout до того, как предыдущие команды в трубе закончены? –
Вот как это должно работать. Тайм-аут '0' заставляет' read' возвращаться немедленно. – Ziffusion
Я понимаю, что тайм-аут '0' должен немедленно вызвать' read'; однако я думал, что это произойдет только после того, как предыдущая команда в трубе закончится, и выход будет передан вызову функции, который содержит 'read'. Исправьте меня, если я ошибаюсь, но если я построю трубу типа 'CMD1 | CMD2 | MyFunction', не работает ли функция только после завершения CMD2? Должна ли выход CMD2 быть немедленно доступным для функции, так что тайм-аут '0' для команды' read' в 'MyFunction' по-прежнему фиксирует ввод? –