При использовании только инструментов POSIX (а в HP-UX не так много других) это сложно, потому что нет удобного способа узнать время модификации файла. С помощью ls -l
вам нужно иметь дело с двумя случаями: последние файлы с месяцем, днем, домом и минутами и старые файлы (> 6 месяцев) с месяцем, днем и годом. (Может быть более простой способ - создать соответствующие настройки локали, но я не знаю, можно ли это сделать в HP-UX.)
#!/bin/sh
set -e -f
set -- $(LC_ALL=C ls -dlog -- "$1")
# $1=permissions $2=link_count $3=size $4,$5,$6=date_time $7...=filename
case $4 in
Jan) month=1;;
Feb) month=2;;
Mar) month=3;;
Apr) month=4;;
May) month=5;;
Jun) month=6;;
Jul) month=7;;
Aug) month=8;;
Sep) month=9;;
Oct) month=10;;
Nov) month=11;;
Dec) month=12;;
esac
case $6 in
*:*) # The timestamp is within the last 6 month, so
# the year is the current or previous year.
current_month=$(LC_ALL=C date +%Y%m)
year=${current_month%??}
current_month=${current_month#????}
case $current_month in 0*) current_month=${current_month#0};; esac
if [ $current_month -lt $month ]; then year=$((year-1)); fi;;
*) year=$6;;
esac
if [ $month -le 9 ]; then month=0$month; fi
day=$5
if [ $day -le 9 ]; then day=0$day; fi
mkdir $year$month$day
Если вы используете какую-то древнюю версию HP-UX, где / bin / sh
- это старая оболочка Bourne, вам может потребоваться заменить / bin / sh
в строке shebang на путь к оболочке POSIX, такой как ksh.
Проблема в том, что когда вы перенаправляете свой вывод, он больше не доступен для следующего перенаправления. Вы можете подключиться к tee
в подоболочке, чтобы сохранить вывод для второго перенаправления:
( cmd | tee -a file2 ) >> file1 2>&1
или если вы хотите увидеть вывод в терминале:
( cmd | tee -a file2 ) 2>&1 | tee -a file1
Чтобы избежать добавления stderr первого tee
в file1
, вы должны перенаправить stderr вашей команды на какой-либо файловый дескриптор (, например. 3 ), а позже снова добавьте это в stdout:
( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
# or
( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1
(спасибо @fra -Сан)
Вы можете :пометить стандартный вывод (с помощью НЕБУФЕРИРОВАННОГО sed, т. е. :sed -u...
), сделать так, чтобы stderr также переходил на стандартный вывод (без тегов, поскольку он не проходил через этот тегирующий sed ), и, таким образом, иметь возможность различать 2 в результирующем файле журнала.
Следующее :является медленным(Его можно серьезно оптимизировать, используя, например, сценарий perl вместо while... ; do... ;done, например, это будет порождать подоболочки и команды в каждой строке! ), странно(кажется, мне нужны 2 этапа {}, чтобы в одном переименовать стандартный вывод, а затем в другом добавить к нему "проваленный" стандартный вывод )и т. д. Но это :" доказательство концепции ", которое попытается максимально сохранить порядок вывода stdout и stderr:
#basic principle (some un-necessary "{}" to visually help see the layers):
# { { complex command ;} | sed -e "s/^/TAGstdout/" ;} 2>&1 | read_stdin_and_redispatch
#exemple:
# complex command = a (slowed) ls of several things (some existing, others not)
# to see if the order of stdout&stderr is kept
#preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
\rm out.file out_AND_err.file unknown unknown2
touch existing existing2 existing3
#and the (slow, too many execs, etc) "proof of concept":
uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs...
# avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.
{
{ for f in existing unknown existing2 unknown2 existing3 ; do ls -l "$f" ; sleep 1; done ;
} | sed -u -e "s/^/${uniquetag}/" ;
} 2>&1 | while IFS="" read -r line ; do
case "$line" in
${uniquetag}*) printf "%s\n" "$line" | tee -a out_AND_err.file | sed -e "s/^${uniquetag}//" >> out.file ;;
*) printf "%s\n" "$line" >> out_AND_err.file ;;
esac;
done;
# see the results:
grep "^" out.file out_AND_err.file
Сzsh
:
cmd >& out+err.log > out.log
В режиме добавления:
cmd >>& out+err.log >> out.log
В zsh
и при условии, что опция mult_ios
не отключена, когда файловый дескриптор (здесь 1 )несколько раз перенаправляется для записи, тогда оболочка реализует встроенный -в tee
, чтобы дублировать вывод на все цели.
Если порядок вывода должен быть:stdout, то stderr ; нет решения только с перенаправлением.
stderr должен храниться во временном файле
cmd 2>>file-err | tee -a file1 >>file2
cat file-err >> file1
rm file-err
Описание:
Единственный способ перенаправить один вывод (fd типа stdout или stderr )в два файла — это воспроизвести его. Команда tee
— правильный инструмент для воспроизведения содержимого файлового дескриптора. Таким образом, первоначальная идея иметь один вывод для двух файлов состоит в том, чтобы использовать:
... | tee file1 file2
Это воспроизводит стандартный ввод tee в оба файла (1 и 2 ), оставляя вывод tee по-прежнему неиспользованным. Но нам нужно добавить (use-a
)и нужна только одна копия. Это решает обе проблемы:
... | tee -a file1 >>file2
Чтобы поставить tee
с stdout (для повторения ), нам нужно использовать stderr непосредственно из команды. В одном случае, если порядок не важен, (порядок вывода будет (скорее всего )сохранен в том виде, в котором он был сгенерирован, то, что будет выведено первым, будет сохранено первым ). Либо:
cmd 2>>file1 | tee -a file2 >>file1
cmd 2>>file1 > >( tee -a file2 >>file1 )
( cmd | tee -a file2 ) >> file1 2>&1
Вариант 2 работает только в некоторых оболочках. Вариант 3 использует дополнительную подоболочку (медленнее ), но использует имена файлов только один раз.
Но если stdoutдолжен быть первым (в зависимости от того, в каком порядке генерируется вывод )нам нужно сохранить stderr, чтобы добавить его в конец файла (первое опубликованное решение ).