stderrとstdoutを(ファイルだけでなく)異なるコマンドにパイプする


11

LDAPのバックアップスクリプトを作成しています。エラーが/ var / log内のファイルに移動し、出力がバックアップフォルダー内の別のファイルに移動するようにします。現在、一時ファイルにリダイレクトしてから、一時ファイルをログに送信しています。私はむしろこれを1ライナーとしてやりたい...

/usr/bin/ldapsearch -x -LLL -b "dc=contoso,dc=com" "(objectclass=*)" -h ldap.server -v 2>>/tmp/ldaptmp.err |
  gzip -c > /mnt/backups/ldap/`date +\%Y\%m\%d`.ldif.gz || 
  logger -t ldapbackup -p local6.err error exit $?

cat /tmp/ldaptmp.err | grep -v "ldap_initialize( ldap://ldap.server )" | 
  grep -v "filter: (objectclass=\*)" |
  grep -v "requesting: All userApplication attributes" >$ERR_LOG
rm -f /tmp/ldaptmp.err

stderrとstdoutを別のパイプにリダイレクトして、このコマンドを1行に圧縮する方法に関するアイデアはありますか?それとももっと良い方法がありますか?


1
このデモをご覧くださいstackoverflow.com/a/16283739/1765658またはこの他の意味のサンプル:unix.stackexchange.com/a/84012/27653
F. Hauri

回答:


10

Unix SEでのこの回答が示すように、

MyWeirdCommand.sh

#!/bin/bash
echo "1 2   3"
echo "4 5   6" >&2

testRedirection.sh:

#!/bin/bash
(./MyWeirdCommand.sh | cut -f1 >stdout.log) 3>&1 1>&2 2>&3 | cut -f3 >stderr.log

実行中の利回り:

  • stderr.log 6

  • stdout.log 1


24

Bashでは、プロセス置換を使用して、追加のファイル記述子を管理できます。これは、ファイル記述子のswapメソッドよりも少し見栄えがする場合があります。

command > >(process_stdout) 2> >(process_stderr)

コマンドは次のようになります。

/usr/bin/ldapsearch -x -LLL -b "dc=contoso,dc=com" "(objectclass=*)" -h ldap.server -v \
  > >( \
    gzip -c > /mnt/backups/ldap/$(date '+%Y%m%d').ldif.gz || 
    logger -t ldapbackup -p local6.err error exit $?
  ) \
  2> >( \
    grep -Ev "ldap_initialize( ldap://ldap.server )|filter: (objectclass=\*)|requesting: All userApplication attributes" > "$err_log" \
  )

1
これが正解です。
Michael Martinez

次のように、ファイルにリダイレクトするのではなくチェーンを保持したい場合は、出力をstderrにリダイレクトして戻すことができます。shf>>(sed -e "s / ^ / stdout:/")2>>( sed -e "s / ^ / stderr:/">&2)
James Moore

>(process)表記の技術名は何ですか?
jchook

1
@jchook最初の文で「プロセス置換」という用語を使用しています。
追って通知があるまで一時停止。

1

これは私がstdoutとstderrを出力してタイムスタンプ付きのファイルを分離する方法です(Debian moreutilsパッケージからtsにパイピング)。

(./my_little_script.pl | ts %F\ %T > out.log) 2>&1 | ts > err.log

PS tsがない場合は、独自のエイリアスを作成します。

alias ts='while IFS= read -r line; do printf "%s %s\n" "$(date +%F\ %T)" "$line"; done'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.