2015-12-28 1 views
0

Я пытаюсь написать функцию, которую я вызываю 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, но это, похоже, не работает.

ответ

0

Попробуйте это:

#!/bin/ksh 

function log 
{ 
    ARG1=$1 
    ARG2=$2 

    if [ ! -t 0 ] 
    then 
     INPUT=$(cat) 
    else 
     INPUT="" 
    fi 

    echo "<datetime>" ${ARG2}${INPUT} 
} 

log 1 "Script executed some action." 

echo "<data from pipe>" | log 2 "this is the output: " 

echo "<data from pipe>" | cat | log 2 "this is the output: " 

Выход:

<datetime> Script executed some action. 
<datetime> this is the output: <data from pipe> 
<datetime> this is the output: <data from pipe> 
+0

Спасибо за ваш ответ @Ziffusion. Кажется, это работает. Я использовал этот трюк, прежде чем использовать 'cat'; однако я не использовал его, потому что думал, что я где-то читаю, где это может столкнуться с состоянием гонки или иметь другие уязвимости. Кажется предпочтительным, чтобы была встроенная команда для этой функции против этой обманчивости с 'cat'. Тем не менее, я тестировал его с помощью своего кода и, похоже, сейчас работает. Мне все еще интересно, почему 'read' не работает в моем примере. Как получается, что оболочка выполняет параметр 'read' timeout до того, как предыдущие команды в трубе закончены? –

+0

Вот как это должно работать. Тайм-аут '0' заставляет' read' возвращаться немедленно. – Ziffusion

+0

Я понимаю, что тайм-аут '0' должен немедленно вызвать' read'; однако я думал, что это произойдет только после того, как предыдущая команда в трубе закончится, и выход будет передан вызову функции, который содержит 'read'. Исправьте меня, если я ошибаюсь, но если я построю трубу типа 'CMD1 | CMD2 | MyFunction', не работает ли функция только после завершения CMD2? Должна ли выход CMD2 быть немедленно доступным для функции, так что тайм-аут '0' для команды' read' в 'MyFunction' по-прежнему фиксирует ввод? –