Jalankan perintah di antara baris pipa bash ...?

4

Saya ingin menjalankan serangkaian perintah pipa yang melakukan banyak audioprocessing. Ini terlihat sebagai berikut dalam pseudocode:

command1 | command2 | command3

Dari command2 dan command3, keduanya mengambil output dari perintah sebelumnya sebagai input (perilaku stdin / stdout biasa).

Sekarang saya ingin menjalankan command1.1 lain setelah command1, yang sama sekali tidak terhubung ke pipa yang berjalan antara command1 dan command2, kecuali untuk itu tidak boleh dijalankan sebelum command1 selesai.

command1 [; after that run command1.1, even if command2 and command3 are still busy] command2 command3

Namun saya tidak tahu bagaimana melakukan ini di bash. Saya sudah mencoba tee, tetapi itu membuat perintah untuk dijalankan segera setelah pipa dibangun. Ada ide?

Terima kasih!

cunei
sumber

Jawaban:

4

Anda dapat mengarahkannya ke subkulit.

command1 & > >(command2 | command3) &
wait $!      # Wait end of process $! (actually the pid of command1)
command_1.1     

Cara lain adalah dengan membuat pipa bernama fifo .
Sebuah skrip harus mirip dengan

MYFIFO=/tmp/myfifo.$$
rm -f $MYFIFO
mkfifo $MYFIFO
command1 > $MYFIFO &
MYPROGRAM_PID=$!
cat $MYFIFO  | command2 | command3 &
wait $MYPROGRAM_PID   # Wait end of process $MYPROGRAM_PID
command_1.1     
Cepat
sumber
4

Bagian penting tentang ini adalah "setelah itu" - satu-satunya konsep yang dimiliki pipa UNIX tentang "setelah itu" adalah, bahwa mereka biasanya menutup, tetapi mereka akan mengeksekusi setelah perintah pertama dimulai , bukan setelah ist telah berakhir .

Jadi yang perlu Anda lakukan adalah menggunakan skrip shell - sesuatu yang memang memiliki konsep "satu demi satu":

echo 'command1' > myscript.sh
echo 'command1.1 >&2' >> myscript.sh
chmod 755 myscript.sh

(Tentu Anda dapat menggunakan editor favorit Anda untuk mencapai hal itu), lalu jalankan

myscript.sh | command2 | command3

Apa yang sekarang terjadi adalah, bahwa output command1akan menjadi output dari skrip shell, sehingga pipa Anda berfungsi. Di dalam skrip Anda, output dari command1.1akan diarahkan ke STDERR dari skrip, sehingga tidak dikirim ke pipa, tetapi ke terminal

Eugen Rieck
sumber
Eugen, gema kedua seharusnyaecho 'command1.1 >&2' >> myscript.sh
Romeo Ninov
Mungkin lebih baik ./myscript.shdari myscript.sh; biasanya direktori saat ini tidak termasuk dalam jalur untuk alasan keamanan ...
Hastur
@Hurur Saya meninggalkan semua jalan - dari OQ Saya berasumsi, poster tahu jalannya
Eugen Rieck
2
@EugenRieck Saya setuju, itu bukan untuk Anda atau cunei. Kita semua berharap bahwa jawabannya dapat bermanfaat bagi pembaca lain juga :-) dan, mungkin, salah satu dari mereka dapat melewatkan pada pandangan pertama perbedaan antara perintah yang ada di suatu tempat PATHdan skrip yang, bahkan jika executable ( chmod 755) adalah dalam direktori saat ini, secara default mati dari PATH.
Hastur
2

Konstruksi paling sederhana adalah:

(command1 ; command1.1) | command2 | command3

Ada dua potensi masalah dengan ini. Jika command1.1menghasilkan keluaran apa pun di stdout, itu akan dikirim melalui pipa. Selain command2itu tidak akan melihat EOF di stdin sampaicommand1.1 selesai.

Jika pipa awalnya dipanggil dalam konteks di mana stdout dan deskriptor file stderr keduanya menunjuk ke file struct yang sama, maka ada cara sederhana untuk memperbaiki kedua masalah:

(command1 ; exec 1>&2 command1.1) | command2 | command3

Ini akan menyebabkan stdout dari perintah1.1 mengarah ke stderr, yang tidak dialihkan oleh pipa.

Jika pada awalnya stdout dan stderr mungkin dua deskriptor file yang berbeda, pendekatan di atas dapat digunakan dengan menyembunyikan sementara stdout awal di nomor deskriptor file lain. Jadi kecuali Anda benar-benar harus menjaga stdout dan stderr command1.1terpisah, saya tidak akan mengambil pendekatan itu.

Untuk kelengkapan, jika Anda ingin melakukannya, itu bisa terlihat seperti ini:

(((exec 9>&- command1) ; exec 1>&9 9>&- command1.1) | exec 9>&- command2 | exec 9>&- command3) 9>&1
kasperd
sumber