Apakah aman untuk mengetik perintah lain ke dalam STDIN ketika perintah sebelumnya menulis ke STDOUT?

21

Mungkin ini sudah dijawab sebelumnya, saya akan menyambut tautan ke jawaban lain ...

Jika saya menjalankan perintah shell (di bashshell) seperti berikut:

make

Kemudian ketika output dari makesedang bergulir dari STDOUTdari makeperintah, jika saya mengetik make checkdan tekan entersebelum perintah pertama selesai dieksekusi, ketika makeperintah akhirnya selesai, perintah selanjutnya make checkakan mengambil yang benar dan berjalan.

Pertanyaan saya sederhana:

  1. Apakah ini berbahaya untuk dilakukan?
  2. Adakah potensi perilaku tak terduga dari pengetikan terburu-buru semacam ini?
  3. Mengapa ini bekerja seperti itu?
111 ---
sumber
2
1. Saya harap ini bukan ... Saya sudah melakukan ini selama bertahun-tahun!
John WH Smith

Jawaban:

20

Ini berfungsi seperti itu karena Unix adalah full-duplex. Seperti yang dikatakan Ritchie dalam The UNIX Time-sharing System: A Retrospective :

Satu hal yang tampaknya sepele, namun membuat perbedaan yang mengejutkan begitu orang terbiasa, adalah terminal dupleks I / O bersama-sama dengan read-ahead. Meskipun program umumnya berkomunikasi dengan pengguna dalam hal garis, daripada karakter tunggal, I / O terminal dupleks penuh berarti bahwa pengguna dapat mengetik kapan saja, bahkan jika sistem mengetik kembali, tanpa takut kehilangan atau karakter kacau. . Dengan baca-depan, orang tidak perlu menunggu jawaban untuk setiap baris. Seorang juru ketik yang baik memasukkan dokumen menjadi sangat frustrasi karena harus berhenti sebelum memulai setiap baris baru; bagi siapa pun yang tahu apa yang ingin dikatakannya kelambanan sebagai respons diperbesar secara psikologis jika informasi itu harus dimasukkan sedikit demi sedikit alih-alih dengan kecepatan penuh.

[kutipan akhir]

Yang sedang berkata, ada beberapa program modern yang memakan atau membuang semua jenis huruf; sshdan apt-getdua contoh. Jika Anda mengetik di depan saat sedang berjalan, Anda mungkin menemukan bahwa bagian pertama dari input Anda telah menghilang. Bisa dibayangkan itu bisa menjadi masalah.

ssh remotehost do something that takes 20 seconds
mail bob
Dan has retired. Feel free to save any important files and then do
# ssh exits here, discarding the previous 2 lines
rm -fr *
.
Tandai Plotnick
sumber
Jadi setelah bash fork()s dan execs perintah, apakah perintah pertama masih melekat STDINpada bash shell? Kedengarannya seperti jawabannya tidak, bash sepertinya menjadi buffering untuk perintah selanjutnya. Apakah itu benar?
111 ---
Kecuali Anda memberi tahu shell untuk mengarahkan stdin dari perintah, perintah tersebut akan memiliki stdin yang sama dengan shell. Apa pun yang Anda ketik dibaca oleh proses pertama yang membacanya. Shell sengaja tidak mencoba membaca apa pun saat perintah sedang berjalan, dan menunggu hingga perintah berhenti. Banyak hal menjadi lebih kompleks jika Anda menempatkan perintah di latar belakang &.
Mark Plotnick
Jadi apakah STDINditangani secara fifo? Dan saya mengira bahwa kecuali proses anak dari bash secara eksplisit menutup pegangan file yang diwarisi STDINmaka masih bisa membaca dari mengetik tambahan?
111 ---
Ya, semua input terminal ditangani FIFO. Tidak yakin saya mengerti pertanyaan kedua Anda. Proses anak - perintah yang digunakan shell - biasanya tidak secara eksplisit menutup stdinnya; shell melangkah keluar dari jalan dan membiarkan perintah membaca semua yang diinginkan, kemudian anak berhenti dan shell melanjutkan membaca.
Mark Plotnick
Ya Anda menjawab kedua pertanyaan tindak lanjut saya dengan sangat jelas, terima kasih!
111 ---
12

Perilaku dasar yang Anda lihat adalah bahwa input duduk di buffer di suatu tempat sampai terbaca (yah, jika Anda mengetik cukup, akhirnya buffer akan terisi, dan sesuatu akan hilang, itu akan banyak mengetik). Sebagian besar hal yang dijalankan oleh make tidak dibaca dari STDIN, sehingga tetap dalam buffer.

Bahayanya adalah bahwa perintah yang salah membaca input Anda. Misalnya, makememanggil sesuatu yang memutuskan untuk meminta Anda, dan kemudian mungkin membaca perintah Anda berikutnya sebagai jawaban. Betapa berbahayanya itu tergantung pada perintah, tentu saja. (Mereka mungkin juga menyiram semua input terlebih dahulu, hanya membuang input Anda sebelumnya.)

Satu perintah, yang biasa digunakan dalam Makefiles, yang mungkin melakukannya adalah TeX. Jika menemui kesalahan (dan belum diberi bendera untuk tidak pernah meminta pengguna), itu akan menanyakan bagaimana Anda ingin melanjutkan.

Sebuah pilihan yang lebih baik mungkin untuk menjalankan: make && make check.

derobert
sumber
8
  1. Nah, semi-jelas, Anda seharusnya tidak menjalankan perintah kedua yang tergantung pada perintah pertama ( make, dalam contoh Anda) telah selesai dengan sukses. Misalnya, make foo Enter> ./foo Enter bisa menimbulkan masalah. Anda mungkin ingin mencoba membiasakan mengetik seperti make && make check, di mana perintah kedua hanya akan dijalankan jika yang pertama berhasil.
  2. Secara teori dimungkinkan bahwa perintah pertama (proses) dapat membaca bagian dari perintah kedua, atau menghapusnya dari buffer input terminal. Jika itu memakan enam karakter pertama make check, Anda akhirnya akan mengeksekusi perintah heck, yang mungkin tidak ada pada sistem Anda (tetapi mungkin sesuatu yang buruk). Jika perintah pertama adalah sesuatu yang jinak yang Anda tahu dan percayai, saya tidak langsung melihat masalah.
  3. Bagaimana / mengapa ini bekerja? Sistem menyangga input keyboard. Ini seperti e-mail: Anda dapat mengirim seseorang lima pesan dalam waktu singkat, dan mereka akan duduk di Kotak Masuk, menunggunya membacanya. Demikian pula, selama perintah pertama tidak membaca dari keyboard, perintah yang Anda ketikkan akan duduk dan menunggu shell untuk membacanya. Ada batas berapa banyak "tipe-depan" dapat disangga, tetapi biasanya beberapa ratus karakter (jika tidak beberapa ribu).
Scott
sumber
2
Untuk poin 1, bayangkan bahwa perintah tidak berhubungan, yaitu lsdan mountmisalnya. Saya mencoba memahami bagaimana input buffered ditangani. Terima kasih atas jawabannya.
111 ---