2016-09-21 8 views
0

У меня есть сценарий bash, чтобы добавить временную метку к каждой записи файла журнала, но я застрял в преобразовании ее в синтаксис оболочки korn. Я читал, что оболочка korn не похожа на подоболочку. Я попытался использовать функцию, но это не сработало. В частности, я попытался преобразовать всю строку exec в синтаксис korn. Может кто-нибудь, пожалуйста, взгляните и помогите мне?Подстановка замещения процесса в ksh (для изменения stdout)

#!/usr/bin/bash 

exec > >(
    while read line ; do 
     echo "$(date '+%Y%m%d %H:%M:%S') ${line}" 
    done > n.log 
) 2>&1 

echo 'first line; should have an initial timestamp' 
sleep 2 
echo 'printed two seconds later, should have a timestamp with a comparable offset' 
+0

Посмотрите здесь ... http://unix.stackexchange.com/a/26797 –

+0

Какие ** ** конкретные реализации КШ? Это был бы совсем другой ответ для подлинного Дэвида Корна ksh93 против mksh или pdksh. –

+1

BTW, предоставленный код bash действительно, ** действительно ** неэффективен ('$ (date)' запускает подоболочку, а затем выполняет внешний подпроцесс в этой подоболочке - для выполнения каждой отдельной строки требуется много накладных расходов вывод). Если вы использовали современную версию (4.1? 4.2?) Bash с встроенной поддержкой strftime, встроенную в printf, вы могли бы значительно снизить эксплуатационные издержки этого фильтра. –

ответ

1

Переносная вещь, которая будет работать в любой совместимой с POSIX оболочкой, заключается в использовании именованного FIFO.

Здесь расширение ksh (printf %()T) также доступно в недавнем bash, чтобы избежать необходимости запускать date внутри подоболочки.

mkfifo log.fifo 
(while IFS= read -r line; do 
    printf '%(%Y%m%d %H:%M:%S)T ' 
    printf '%s\n' "$line" 
done >n.log <log.fifo) & 
exec >log.fifo 
+0

Как 'bash', так и' ksh' (по крайней мере версия, поставляемая с OS X, независимо от того, что есть) может вообще не указывать второй аргумент, чтобы напечатать текущую дату/время. – chepner

+0

@Charles Спасибо за помощь. Теперь он будет работать как в bash, так и в ksh, поэтому мне не нужны два кода для разных оболочек. – Ben

+0

@chepner, в bash 4.4.0, 'printf '% (% Y) T \ n' '' 'дает мне 1969 год. Таким образом, не представляется возможным выполнить этот маршрут, если требуется параметризованный компонент в той же строке формата ... хотя, я полагаю, можно использовать два отдельных вызова 'printf'. –

0

Немного расширения на отличном ответ Чарльза: сделать его более явным путем создания отдельных функций для вывода модификации и для основного функционального кода; без именованных каналов, после того, как вы закончите, вам нечего убирать.

print_with_timestamps() { 
    (while IFS= read -r line; do 
    printf '%(%Y%m%d %H:%M:%S)T ' 
    printf '%s\n' "$line" 
    done 
) > n.log 2>&1 
} 

main() { 
echo 'first line; should have an initial timestamp' 
sleep 2 
echo 'printed two seconds later, should have a timestamp with a comparable offset' 
} 

main | print_with_timestamps