Pipa stderr dan stdout ke berbagai perintah (tidak hanya ke file)


11

Saya membuat skrip cadangan untuk ldap. Saya ingin kesalahan untuk pergi ke file di / var / log dan output untuk pergi ke file lain di folder cadangan. Saat ini saya sedang mengarahkan kembali ke file temp dan kemudian mengirimkan file temp ke log. Saya lebih suka melakukan ini sebagai 1 liner sekalipun ...

/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

Ada ide tentang cara mengarahkan stderr dan stdout ke pipa yang berbeda untuk menyingkat perintah ini menjadi 1 baris? Atau ada cara yang lebih baik?


1
Lihatlah demonstrasi ini: stackoverflow.com/a/16283739/1765658 atau contoh makna lain ini: unix.stackexchange.com/a/84012/27653
F. Hauri

Jawaban:


10

Seperti yang ditunjukkan oleh jawaban ini di 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

Hasil panen:

  • stderr.log 6

  • stdout.log 1


24

Di Bash, Anda bisa menggunakan subtitusi proses untuk mengelola deskriptor file tambahan untuk Anda. Anda mungkin menemukan ini sedikit lebih rapi daripada metode swap deskriptor file.

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

Perintah Anda mungkin terlihat seperti ini:

/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
Ini jawaban yang benar.
Michael Martinez

Anda mungkin ingin mengarahkan kembali output ke stderr jika Anda ingin menjaga rantai alih-alih mengarahkan ke file, sesuatu seperti ini: sh f>> (sed -e "s / ^ / stdout: /") 2>> ( sed -e "s / ^ / stderr: /"> & 2)
James Moore

Apa nama teknis untuk >(process)notasi?
jchook

1
@ jchook Saya menggunakan istilah dalam kalimat pertama: "proses substitusi".
Dijeda sampai pemberitahuan lebih lanjut.

1

Ini adalah bagaimana saya mencetak stdout dan stderr untuk memisahkan file dengan cap waktu (perpipaan ke ts dari paket moreutils Debian):

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

PS jika Anda tidak memiliki ts, buat alias sendiri:

alias ts='while IFS= read -r line; do printf "%s %s\n" "$(date +%F\ %T)" "$line"; done'
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.