Cara mengalihkan stderr ke file

Saat menggunakan nohup untuk meletakkan perintah untuk dijalankan di latar belakang, beberapa konten muncul di terminal.

cp: error reading ‘/mnt/tt/file.txt’: Input/output errorcp: failed to extend ‘/mnt/tt/file.txt’: Input/output error

Saya ingin menyimpan konten itu ke file.

Ada dua aliran keluaran utama di Linux (dan OS lainnya), keluaran standar (stdout) dan kesalahan standar (stderr). Pesan kesalahan, seperti yang Anda tampilkan, dicetak ke kesalahan standar. Operator pengalihan klasik (command > file) hanya mengalihkan output standar, jadi kesalahan standar masih ditampilkan di terminal. Untuk mengarahkan stderr juga, Anda memiliki beberapa pilihan:

  1. Redirect stdout ke satu file dan stderr ke file lain:

    command > out 2>error
  2. Mengalihkan stdout ke berkas (>out), dan kemudian mengarahkan stderr ke stdout (2>&1):

    command >out 2>&1
  3. Redirect kedua ke file (ini tidak didukung oleh semua kerang, bash dan zsh mendukungnya, misalnya, tetapi sh dan ksh tidak):

    command &> out

Untuk informasi lebih lanjut tentang berbagai operator kontrol dan pengalihan, lihat di sini.

Hal pertama yang perlu diperhatikan adalah bahwa ada beberapa cara tergantung pada tujuan dan cangkang anda, oleh karena itu ini membutuhkan sedikit pemahaman tentang berbagai aspek. Selain itu, perintah tertentu seperti time dan strace tulis output ke stderr secara default, dan mungkin atau mungkin tidak menyediakan metode pengalihan khusus untuk perintah itu

Teori dasar di balik pengalihan adalah bahwa proses yang dihasilkan oleh shell (dengan asumsi itu adalah perintah eksternal dan bukan shell built-in) dibuat melalui fork() dan execve() syscall, dan sebelum itu terjadi syscall lain dup2() melakukan pengalihan yang diperlukan sebelum execve() terjadi. Dalam hal ini, pengalihan diwarisi dari shell induk. The m&>n dan m>n.txt menginformasikan shell tentang cara melakukan open() dan dup2() syscall (lihat juga Cara kerja pengalihan masukan, Apa perbedaan antara pengalihan dan pipa, dan Apa arti & amp; sebenarnya dalam pengalihan keluaran )

Pengalihan Shell

Paling khas, adalah melalui 2> di Kerang seperti Bourne, seperti dash (yang symlinked ke /bin/sh) dan bash; pertama adalah shell default dan POSIX-compliant dan yang lainnya adalah apa yang sebagian besar pengguna gunakan untuk sesi interaktif. Mereka berbeda dalam sintaks dan fitur, tetapi untungnya bagi kami pengalihan aliran kesalahan berfungsi sama (kecuali &> non standar satu). Dalam kasus csh dan turunannya, pengalihan stderr tidak cukup bekerja di sana.

Mari kita kembali ke 2> bagian. Dua hal penting untuk diperhatikan: > berarti operator pengalihan, di mana kita membuka file dan 2 integer adalah singkatan dari stderr file descriptor; sebenarnya ini persis bagaimana standar POSIX untuk bahasa shell mendefinisikan redirection di bagian 2.7:

[n]redir-op word

Untuk sederhana > pengalihan, yang 1 integer tersirat untuk stdout, yaitu. echo Hello World > /dev/null sama saja dengan echo Hello World 1>/dev/null. Perhatikan, bahwa operator integer atau redirection tidak dapat dikutip, jika tidak shell tidak mengenalinya, dan sebaliknya memperlakukan sebagai string teks literal. Sedangkan untuk spasi, penting bahwa integer berada tepat di sebelah operator pengalihan, tetapi file dapat berada di sebelah operator pengalihan atau tidak, yaitu. command 2>/dev/null dan command 2> /dev/null akan bekerja dengan baik.

Sintaks yang agak disederhanakan untuk perintah tipikal di shell adalah

 command [arg1] [arg2]  2> /dev/null

Kuncinya di sini adalah bahwa pengalihan dapat muncul di mana saja. Itu keduanya 2> command [arg1] dan command 2> [arg1] valid. Perhatikan bahwa untuk bash shell, ada ada ada &> cara untuk mengalihkan aliran stdout dan stderr secara bersamaan, tetapi sekali lagi - ini spesifik bash dan jika Anda berjuang untuk portabilitas skrip, itu mungkin tidak berfungsi. Lihat juga Ubuntu Wiki dan >>Apa perbedaan antara & amp; dan 2 & amp; 1.

Catatan: The > operator pengalihan truncates file dan menimpa itu, jika file tersebut ada. The 2>> dapat digunakan untuk menambahkan stderr untuk mengajukan.

Jika Anda mungkin memperhatikan, > dimaksudkan untuk satu perintah tunggal. Untuk skrip, kita dapat mengarahkan aliran stderr dari seluruh skrip dari luar seperti di myscript.sh 2> /dev/null atau kita bisa menggunakan exec built-in. Exec built-in memiliki kekuatan untuk memutar ulang aliran untuk seluruh sesi shell, sehingga untuk berbicara, baik secara interaktif atau melalui skrip. Sesuatu seperti

#!/bin/shexec 2> ./my_log_file.txtstat /etc/non_existing_file

Dalam contoh ini, file log harus menunjukkan stat: cannot stat '/etc/non_existing_file': No such file or directory.

Cara lain adalah melalui fungsi. As Cinderella dicatat dalam jawabannya, kita dapat menulis deklarasi fungsi dengan pengalihan yang sudah terpasang, yaitu

some_function(){    command1    command2} 2> my_log_file.txt

Perintah menulis ke stderr secara eksklusif

Perintah seperti time dan strace tulis outputnya ke stderr secara default. Dalam kasus time perintah, satu-satunya alternatif adalah untuk mengarahkan output dari seluruh perintah , yaitu

time echo foo 2>&1 > file.txt

atau, daftar Sinkron atau subkulit dapat dialihkan jika Anda ingin memisahkan output ( seperti yang ditunjukkan pada artikel terkait ):

{ time sleep 1 2> sleep.stderr ; } 2> time.txt

Perintah lain, seperti strace atau dialog menyediakan sarana untuk mengarahkan stderr. strace memiliki -o <filename.txt> opsi yang memungkinkan menentukan nama file di mana output harus ditulis. Ada juga pilihan untuk menulis textfile untuk setiap subproses yang strace melihat. The dialog perintah menulis antarmuka pengguna teks ke stdout tetapi output ke stderr, jadi untuk Simpan outputnya ke variabel (karena var=$(...) dan pipeline hanya menerima stderr) kita perlu menukar deskriptor file

result=$(dialog --inputbox test 0 0 2>&1 1>/dev/tty);

tapi selain itu, ada --output-fd bendera, yang juga bisa kita manfaatkan. Ada juga metode bernama pipa. Saya sarankan membaca posting terkait tentang dialog perintah untuk deskripsi menyeluruh tentang apa yang terjadi.

@ terdon ini adalah pertanyaan yang lebih spesifik, dan itu benar muncul di pencarian google untuk pertanyaan yang lebih spesifik, yang merupakan hal yang baik.

@nroose ya, dan itu akan terus muncul, itu tidak akan berubah. Tetapi setiap jawaban baru harus pergi ke pertanyaan yang lebih umum.