Bash cara untuk memeriksa apakah suatu proses sudah berjalan di latar belakang (dan lewati eksekusi ulang berdasarkan itu)?

11

Bisakah saya membuat baris perintah bash yang hanya menjalankan perintah tertentu jika prosesnya belum berjalan (di latar belakang)?

Bagaimana saya memeriksa *, jika suatu perintah sudah berjalan?

(jadi saya bisa menambahkan perintah berikutnya dengan &&di antara mereka sehingga yang berikutnya hanya dijalankan jika yang pertama benar).

*: uji, tentukan, temukan, cari tahu

n611x007
sumber
3
ps -ef | grep -v grep | grep "process_name" || run_command_here
Rahul Patil
1
@RahulPatil dapat Anda gunakan pgrep "process_name"sebagai gantips | grep | grep
buru
hmm, saya lupa itu ..: D
Rahul Patil
1
Mengapa Anda tidak menggunakan file "kunci", dan ketika Anda meluncurkan kedua kalinya, itu hanya akan diluncurkan ketika file kunci hilang.
BitsOfNix
cara terbaik untuk memeriksa apakah ada proses: stackoverflow.com/questions/3043978/…
Trevor Boyd Smith

Jawaban:

3

Saya telah menggunakan teknik ini dari waktu ke waktu:

$ pgrep <process name> || <process name>

Sebelum pgrepitu dulu dilakukan dengan cara ini:

$ ps -eaf | grep -q <[p]rocess name> || <process name>

contoh

Bit dengan [p]membuatnya sehingga greptidak akan menemukan dirinya sebagai hasilnya.

$ ps -eaf | grep -q [s]leep || sleep 10
slm
sumber
2

Ini bisa rumit, karena Anda dapat memiliki contoh terpisah dari proses yang sama yang hidup secara mandiri. Misalnya server mendengarkan pada port yang berbeda, atau layanan berjalan sebagai pengguna yang berbeda. Untuk membedakan di antara contoh-contoh ini, Anda perlu memberi mereka masing-masing tag unik. Tag sering berupa file, tetapi bisa berupa soket lokal di namespace abstrak, port TCP, dll. - pengidentifikasi unik apa pun akan melakukannya. Ketika tag adalah file, itu bisa berupa file biasa yang berisi ID proses (pidfile), atau pipa atau soket bernama tempat file itu mendengarkan, dll. Idealnya, tag adalah titik akhir komunikasi yang memungkinkan klien untuk terhubung untuk proses itu.

Setiap jenis tag yang berbeda ini menghasilkan cara yang berbeda untuk memeriksa apakah instance yang Anda cari sudah aktif dan berjalan. Misalnya, dengan soket file lokal, coba sambungkan ke sana, dan mulai prosesnya jika tidak ada proses mendengarkan pada soket itu. Jika tag tersebut adalah pidfile, periksa apakah ada proses dengan ID proses itu, tetapi berhati-hatilah bahwa ini rapuh, karena jika prosesnya telah mati, mungkin ada proses yang tidak terkait yang telah menggunakan kembali ID-nya. Berhati-hatilah bahwa jika dua klien mencoba mencapai proses dalam kerangka waktu yang singkat, mereka mungkin menemukan bahwa proses tersebut tidak ada dan keduanya berusaha untuk memulainya; melindungi dengan benar dari kondisi balapan ini bisa rumit.

Lebih mudah untuk mengelola instance ketika mereka semua dimulai oleh proses penyelia yang sama, dan proses pengawas mendeteksi ketika instance mati dan bereaksi sesuai. Banyak program pemantauan layanan yang dapat melakukan ini.

Jika program tidak merespons pada titik akhir komunikasi yang diketahui dan tidak dikelola oleh program pengawas, tag orang miskin adalah pidfile: file yang berisi ID proses. Saat Anda memulai proses, tulis pid ke file dengan nama yang sudah diatur sebelumnya. Ketika Anda membutuhkan proses untuk eksis, baca pidfile dan lihat apakah ada proses dengan pid itu. Saat Anda membunuh prosesnya, hapus pidfile. Masalah yang paling menonjol dengan pidfile yang tidak diawasi adalah bahwa jika proses mati, pidnya dapat digunakan kembali oleh beberapa proses yang tidak terkait. Anda setidaknya harus memeriksa nama proses atau proses yang dapat dieksekusi untuk memastikan bahwa Anda berbicara dengan proses yang benar. Banyak varian unix yang memiliki perintah pgrep :pgrep SOMENAME mencantumkan proses yang namanya mengandung SOMENAME sebagai substring, dengan opsi tambahan untuk membatasi pengguna tertentu, untuk memerlukan kecocokan yang tepat, untuk mengubah mana dari beberapa kemungkinan gagasan "nama proses" yang digunakan, dll.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
1

Anda bisa menggunakan pendekatan ini:

if [[ -z $(ps -C appname -opid=) ]]; then
    appname && secondapp
fi
jasonwryan
sumber
1

Pilihan lain:

  • pgrep -xq processname
    • Hanya cocok dengan 15 karakter pertama di GNU / Linux
    • Tidak termasuk leluhur di OS X
  • ps -eo comm= | sed 's|.*/||' | grep -xq processname
    • Hanya cocok dengan 15 karakter pertama di GNU / Linux
    • sed 's|.*/||' menghapus bagian dirname pada OS X

Dalam GNU / Linux ps -o commmemotong nama perintah menjadi 15 karakter dan pgrepdan ps -Chanya cocok dengan 15 karakter pertama.

ps -C (nama perintah kecocokan) tidak didukung pada OS X.

Dalam OS X ps -o commmencetak jalur absolut perintah dan ps -co commhanya mencetak nama perintah. Di GNU ps -o commhanya mencetak nama perintah dan -cmemiliki arti berbeda.

Pgrep OS X tidak termasuk proses leluhur (seperti bash, Terminal, atau launchd) tanpa -a. Pgrep GNU memasukkan mereka secara default dan tidak mendukung -a.

grep -xdan pgrep -xjangan menyiratkan -F, jadi gunakan -Fxjika nama proses dapat berisi karakter regex.

Lri
sumber
-C juga tidak tersedia di cygwin saya :)
n611x007
1

Maaf, tetapi semua solusi ini tidak mendukung contab karena baris perintah yang sama akan muncul dua kali dalam hasil 'ps'.

Jadi inilah milik saya:

## Test pour voir si le même script tourne déjà
## Un fichier .pid est utilisé pour stocké le numéro de process
## Si le pid est en train de tourner alors on sort.
lock_file=$0".pid"
[ -r $lock_file ] && read pid <$lock_file
if [ "$pid" -gt 1 ] && [ `ps --no-headers -p "$pid" | wc -l` -gt 0 ] ; then
    echo "WARNING : le process $pid tourne deja : $0"
    ps -edf | grep `basename $0` | grep -v grep
    echo "WARNING : Arrêt de cette instance ($$)."
    exit 7
fi
echo $$ >$lock_file
Francis
sumber
Apa yang kamu minta maaf? Apa itu contab? Apakah maksud Anda memeriksa dari dalam suatu cronpekerjaan?
Anthon
0

Dengan Bash

#!/usr/bin/env bash

[[ $# -eq 0 ]] && { echo -e "Usage:\t\t $0 <Process_name>  <Command here>"; exit 1;  }

ifnotrun(){
        local p=$1
        if ! ps -C "$1" -opid=
        then
                cmd=($@)
                echo ${cmd[@]:1}
        else
                echo "Process \"$p\" Already Running.."
                exit 1
        fi

}

ifnotrun $*

Catatan: - hapus echojika output terlihat OK.

Rahul Patil
sumber
0

Saya akan menjelaskan kasus di mana Anda menjalankan perintah di beckgreoud. "$!" simpan PID dari proses latar belakang terakhir. Jadi, Anda dapat menggunakannya untuk menemukannya di tabel proses mengikuti jawaban di atas:

sleep 4 &
ps -ef | grep -w  $!  ...

Perintah builtin "pekerjaan" - coba ini:

sleep 4&
J=`jobs`
while [ "$J" ]; do
        sleep 1
        jobs # This line flush the jobs' bufer.
        J=`jobs`
done

Mengenai opsi "&&"

Alih-alih && gunakan perintah tunggu. Pada contoh berikut ini, myproc2 tidak akan berjalan sampai myproc1 selesai:

myproc1 &
wait
myproc2
Udi
sumber
0

Dapatkan status proses Anda:

ps -lp $(pgrep <YOUR_PROCESS_NAME>) | tail -1 | awk '{print $11}'

Referensi:

D    uninterruptible sleep (usually IO)
R    running or runnable (on run queue)
S    interruptible sleep (waiting for an event to complete)
T    stopped, either by a job control signal or because it is being traced
W    paging (not valid since the 2.6.xx kernel)
X    dead (should never be seen)
Z    defunct ("zombie") process, terminated but not reaped by its parent

Sebagai contoh, saya telah menggunakannya untuk memutar atau menghentikan sementara proses sox saya pada sesi tmux:

/usr/local/bin/tmux if-shell -t sox "[ $(ps -lp $(pgrep sox) | tail -1 | awk '{print $11}') == 'T' ]" \
  'send -t sox "fg" Enter' \
  'send -t sox C-z'
Jose Alban
sumber
-1

Anda dapat menggunakannya di dalam skrip:

if [ `ps -ef | grep "script.sh" | grep -v grep | wc -l` -gt 1 ] ; then
echo "RUNNING...."
else
echo "NOT RUNNING..."
fi
Prav
sumber