Mulai tugas secara diam-diam di latar belakang

12

Saya tahu bahwa Anda dapat menggunakan ini untuk memulai proses di latar belakang, tanpa mendapatkan pemberitahuan saat proses diletakkan di latar belakang dan ketika dilakukan seperti ini:

(perintah &) &> / dev / null

Namun ini menghapus opsi untuk menjebak ketika proses selesai ( trap child_done CHLD).

Bagaimana saya bisa memiliki keduanya?

Tyilo
sumber

Jawaban:

5

task-spooler dapat membantu Anda.

Seperti di freshmeat.net :

task spooler adalah sistem batch Unix di mana tugas spooled dijalankan satu demi satu. Jumlah pekerjaan yang harus dijalankan sekaligus dapat diatur kapan saja. Setiap pengguna di setiap sistem memiliki antrian pekerjaannya sendiri. Tugas dijalankan dalam konteks yang benar (yaitu enqueue) dari setiap shell / proses, dan output / hasilnya dapat dengan mudah dipantau. Ini sangat berguna ketika Anda tahu bahwa perintah Anda bergantung pada banyak RAM, banyak penggunaan disk, memberikan banyak output, atau untuk alasan apa pun lebih baik tidak menjalankan semuanya pada saat yang sama, sementara Anda ingin tetap menggunakan sumber daya Anda sibuk untuk manfaat maksimum. Antarmuka memungkinkan penggunaannya dengan mudah dalam skrip.

Task-spooler tersedia di Debian , Ubuntu dan distro lainnya.

Ini memungkinkan Anda memiliki antrian tugas untuk dijalankan, dan mengakses hasilnya hanya sesuai keinginan.

Sebagai contoh:

$ tsp sleep 5
0 
$ tsp sleep 5 
1
$ tsp
ID   State      Output               E-Level  Times(r/u/s)   Command [run=1/1]
2    running    /tmp/ts-out.ZWn6Le                           sleep 5
1    finished   /tmp/ts-out.Fhlcle   0        5.00/0.00/0.01 sleep 5

Jika Anda menjalankan banyak pekerjaan di latar belakang, itu pasti akan membantu Anda.

Anda dapat menjalankannya secara berurutan atau dalam jumlah slot yang telah ditentukan. Anda juga dapat membuat dependensi di antara tugas-tugas (jalankan task1 hanya jika task0 berhasil diselesaikan).

Raúl Salinas-Monteagudo
sumber
3

Inilah cara melakukannya di keduanya {ba,z}sh.

Menggunakan fungsi membantu tidak perlu menyimpan dan mengembalikan keadaan zsh's monitorvariabel dengan menggunakan setopt local_options.

# Run the command given by "$@" in the background
silent_background() {
  if [[ -n $ZSH_VERSION ]]; then  # zsh:  /superuser//a/1285272/365890
    setopt local_options no_notify no_monitor
    "$@" &
  elif [[ -n $BASH_VERSION ]]; then  # bash: /programming//a/27340076/5353461
    { 2>&3 "$@"& } 3>&2 2>/dev/null
  else  # Unknownness - just background it
    "$@" &
  fi
}

Gunakan ini sebagai berikut:

trap 'echo child done' CHLD
silent_background sleep 1

Akan menghasilkan child donepesan yang diharapkan .

Tom Hale
sumber
lihat unix.stackexchange.com/q/456549/4778 untuk penjelasan yang penuh harapan.
ctrl-alt-delor
2

Pengalihan output perintah tampaknya tidak relevan karena pemberitahuan dikirim oleh shell ketika pekerjaan dimulai secara tidak sinkron. Lebih tepatnya, ini adalah fitur shell (fonctionality) yang terkait dengan kontrol pekerjaan .

Di sini, kutipan yang berasal dari "Bash Reference Manual", bab "Kontrol Pekerjaan", bagian satu.

Shell mengaitkan PEKERJAAN dengan setiap pipa. Itu menyimpan tabel pekerjaan yang sedang dieksekusi, yang mungkin terdaftar dengan jobsperintah. Ketika Bash memulai pekerjaan secara tidak sinkron, ia mencetak garis yang terlihat seperti:

[1] 25647

menunjukkan bahwa pekerjaan ini adalah pekerjaan nomor 1 dan bahwa ID proses dari proses terakhir dalam pipa yang terkait dengan pekerjaan ini adalah 25647. Semua proses dalam satu pipa tunggal adalah anggota dari pekerjaan yang sama. Bash menggunakan abstraksi PEKERJAAN sebagai dasar untuk kontrol pekerjaan.

Perhatikan bahwa skrip shell tidak menampilkan pemberitahuan ini.

$ cat test
#!/bin/bash

true & echo true
$ ./test
true

Kenyataannya

Zsh

Dokumentasi Zsh memberikan indikasi serupa tentang pemberitahuan ini, lihat man 1 zshmisc, bagian "JOBS". Notifikasi ini tidak ditampilkan ketika kontrol pekerjaan dinonaktifkan.

MONITOR ( -m , ksh: -m )

    Izinkan kontrol pekerjaan. Diatur secara default di shell interaktif.

zsh_prompt % setopt no_monitor
zsh_prompt % true & echo true
true
zsh_prompt %
zsh_prompt % 

Pesta

Tampaknya Bash selalu menampilkan misalnya [1] 25647. Misalnya, "pemberitahuan akhir" [1]+ Done truetidak ditampilkan ketika kontrol pekerjaan dinonaktifkan.

bash_prompt $ true & echo true
[1] 25647
true
bash_prompt $ 
[1]+  Done                    true

Kontrol pekerjaan dinonaktifkan

bash_prompt $ set +m       # disable job control
bash_prompt $ true & echo true
[1] 25685
bash_prompt $
bash_prompt $

Kesimpulan

Saya tidak tahu apakah menonaktifkan kontrol pekerjaan untuk menyembunyikan notifikasi adalah hal yang baik?

Sumber daya

Fólkvangr
sumber
1

Anda dapat meminta zshsebagai shell non-interaktif untuk menonaktifkan pemberitahuan pekerjaan.

zsh -c '
   trap "echo trapped child_done" CHLD
   sleep 5 &
   #wait
   sleep 10 # simulate other running cmds
   echo script done
'
nad
sumber
0

Lihat contoh berikut:

trap 'echo "DONE"' 0
{ find /usr & } &> /dev/null
wait

Itu bekerja dengan baik. Tidak perlu ( ): itu membuat subkulit yang tidak diperlukan. { }hanyalah perintah pengelompokan.

Gilles Quenot
sumber
Itu mencetak [2] 49591dan [2] + 49591 exit 1 find /usr, kapan harus mencetak keduanya?
Tyilo
Maaf, Anda salah mengerti pertanyaan Anda.
Gilles Quenot
0

Ini adalah pertanyaan lama, tetapi kemungkinan jawaban (dalam bash, tidak diuji dengan zsh) adalah dengan menggunakan kontrol pekerjaan di subkulit: (command & wait)

Catatan: bash menekan pesan pekerjaan latar belakang mulai / berakhir di subkulit, dan tidak perlu pengalihan.

Philippe
sumber
Saya pikir Anda melewatkan bagian dengan jebakan. Sejauh yang saya mengerti pertanyaan proses harus dimulai, sesuatu akan dilakukan ketika proses dijalankan dan kemudian ketika proses selesai sesuatu yang lain harus dieksekusi. Dengan solusi Anda, Anda memulai proses menunggu di subkulit dan shell utama menunggu untuk subkulit. Ini menghilangkan pesan, tetapi Anda tidak dapat melakukan sesuatu secara paralel.
Raphael Ahrens
Tidak, (sleep 5 & wait)penundaan 5 detik.
Tom Hale