Bagaimana menentukan apakah suatu proses sedang berjalan atau tidak dan menggunakannya untuk membuat skrip shell bersyarat?

108

Bagaimana saya bisa menentukan apakah suatu proses sedang berjalan atau tidak dan kemudian memiliki skrip bash mengeksekusi beberapa hal berdasarkan kondisi itu?

Sebagai contoh:

  • jika proses abcsedang berjalan, lakukan ini

  • jika tidak berjalan, lakukan itu.

Nirmik
sumber
1
Merasa penting untuk dicatat bahwa tidak ada solusi di bawah ini yang mempertimbangkan kondisi proses. Sebuah komentar pada salah satu pertanyaan saya membawa saya ke sini, tetapi jawaban atas pertanyaan itu memberi saya petunjuk tentang keadaan program yang berbeda, seperti zombieproses '(Bukan apa yang saya gambarkan sebagai proses "berjalan"). Daftar lengkap apa yang STATkolom nilai, dalam output dari ps, menunjukkan di sini untuk mereka yang cenderung menulis jawaban yang mengakomodasi ini, atau mengedit sendiri.
user66001
Ada cara terbaik untuk memeriksa proses yang ada: stackoverflow.com/questions/3043978/…
Trevor Boyd Smith

Jawaban:

166

Skrip bash untuk melakukan sesuatu seperti itu akan terlihat seperti ini:

#!/bin/bash

# Check if gedit is running
# -x flag only match processes whose name (or command line if -f is
# specified) exactly match the pattern. 

if pgrep -x "gedit" > /dev/null
then
    echo "Running"
else
    echo "Stopped"
fi

Script ini hanya memeriksa untuk melihat apakah program "gedit" sedang berjalan.

Atau Anda hanya dapat memeriksa apakah program tidak berjalan seperti ini:

if ! pgrep -x "gedit" > /dev/null
then
    echo "Stopped"
fi
John Vrbanac
sumber
@DreadPirateShawn dapatkah Anda memberi tahu saya mengapa menggunakan / dev / null dan bukan hanya 0? Menggunakan nomor membuat kode lebih mudah dibaca, setidaknya untuk noob (seperti saya). Tidak ada redirect, no nothing
Silviu
2
@ Silviu ya? Googling /dev/null: "/ dev / null mengarahkan ulang output standar perintah ke perangkat null, yang merupakan perangkat khusus yang membuang informasi yang ditulis padanya" ... menggunakan 0akan mengarahkan output perintah ke file yang disebut 0. Dalam hal ini, saya sarankan menjadi lebih nyaman dengan > /dev/null- Anda akan melihatnya di mana-mana, karena ini adalah cara standar / tepat untuk membuang output.
DreadPirateShawn
Woot terima kasih, saya menggunakan ini untuk skrip kecil yang bagus yang memeriksa apakah suatu program berjalan sebelum dijalankan. (walaupun saya harus memperpanjangnya sedikit karena executable google chrome tidak memiliki nama yang sama dengan menjalankan perintahnya, nama exec hanya chrome.)
Cadangan
3
Harap tambahkan -xparameter untuk pgrepmencari aplikasi yang tepat atau jika tidak maka akan mendapatkan kesalahan yang benar jika menemukan string yang sama di dalam nama aplikasi lain. Saya hanya menghabiskan 1 jam untuk mencari tahu.
Thanos Apostolou
1
Untuk memeriksa apakah program tidak berjalan gunakan! pgrep
Mohammed Noureldin
36

Solusi apa pun yang menggunakan sesuatu seperti ps aux | grep abcatau pgrep abccacat.

Mengapa?

Karena Anda tidak memeriksa apakah proses tertentu sedang berjalan, Anda memeriksa apakah ada proses yang berjalan yang cocok abc. Setiap pengguna dapat dengan mudah membuat dan menjalankan nama yang dapat dieksekusi abc(atau yang mengandung abcsuatu tempat dalam nama atau argumennya), menyebabkan hasil positif palsu untuk pengujian Anda. Ada berbagai opsi yang dapat Anda terapkan ps, grepdan pgrepuntuk mempersempit pencarian, tetapi Anda masih tidak akan mendapatkan tes yang andal.

Jadi, bagaimana cara saya andal menguji untuk proses berjalan tertentu?

Itu tergantung pada apa yang Anda butuhkan untuk tes.

Saya ingin memastikan bahwa layanan abc berjalan, dan jika tidak, mulai saja

Inilah tujuan init dan pemula. Mereka akan memulai layanan dan memastikan pidnya disimpan di pidfile. Cobalah untuk memulai layanan lagi (melalui init atau pemula) dan ia akan memeriksa pidfile, dan mulai jika tidak ada, atau batalkan jika sudah berjalan. Ini masih belum 100% andal, tapi sedekat yang Anda dapatkan.

Lihat Bagaimana saya dapat memeriksa untuk melihat apakah server permainan saya masih berjalan ... untuk solusi lain.

abc adalah skrip saya. Saya perlu memastikan hanya satu contoh skrip saya berjalan.

Dalam hal ini, gunakan file kunci atau file kunci. Misalnya

#!/usr/bin/env bash

if ! mkdir /tmp/abc.lock; then
    printf "Failed to acquire lock.\n" >&2
    exit 1
fi
trap 'rm -rf /tmp/abc.lock' EXIT  # remove the lockdir on exit

# rest of script ...

Lihat Bash FAQ 45 untuk cara mengunci lainnya.

geirha
sumber
3
Meskipun secara teknis ini benar, saya belum pernah mengalami masalah seperti itu di kehidupan nyata. Sebagian besar program tidak mengubah nama mereka dengan cara yang merusak skrip. Jadi, untuk skrip sederhana, sesuatu seperti pgrepatau pssangat memadai dan pendekatan Anda sepertinya berlebihan. Jika Anda menulis skrip untuk distribusi publik, Anda harus menulisnya dengan cara yang paling aman.
Scott Severance
2
@ScottSeverance Program mengubah nama bukan masalah; itu akan memerlukan intervensi apa pun. Pengguna lain yang menjalankan program yang sama, atau program lain dengan nama serupa yang tiba-tiba akan menyebabkan skrip mendapatkan positif palsu dan karenanya melakukan hal yang salah. Saya lebih suka "bekerja" daripada "kebanyakan bekerja".
geirha
2
Saya salah bicara. Tetapi banyak dari kita menjalankan sistem pengguna tunggal. Dan dalam situasi beberapa pengguna, mudah juga menangkap nama pengguna.
Scott Severance
1
bagaimana jika skrip Anda gagal saat runtime dan mati sebelum membuka kunci file?
jp093121
2
@ jp093121 Perangkap EXIT dipicu ketika skrip keluar. Apakah itu keluar karena mencapai akhir skrip, perintah keluar, atau menerima sinyal (yang dapat ditangani), rmperintah dijalankan. Jadi selama itu berakhir setelah jebakan diatur, kunci harus hilang.
geirha
18

Inilah yang saya gunakan:

#!/bin/bash

#check if abc is running
if pgrep abc >/dev/null 2>&1
  then
     # abc is running
  else
     # abc is not running
fi

Dalam bahasa Inggris biasa: jika 'pgrep' mengembalikan 0, proses sedang berjalan, jika tidak, maka tidak.


Bacaan terkait:

Bash Scripting :: Perbandingan String

Manual Ubuntu pgrep

Zuul
sumber
terima kasih! saya mencoba ini juga n bekerja dengan baik juga :)
Nirmik
pgrepmemiliki batas "fitur" 15 karakter yang sama yang disebutkan sebelumnya, jadi misalnya pgrep gnome-power-managerjuga akan gagal
Thorsen
1
Pastikan Anda menggunakan -xopsi pgrep : "Hanya proses pencocokan yang namanya (atau baris perintah jika -f ditentukan) sama persis dengan polanya."
Alastair Irvine
5

Saya biasanya memiliki pidof -x $(basename $0)pada skrip saya untuk memeriksa apakah sudah berjalan.

Rommel Cid
sumber
2

Mengisi gagasan @ rommel-cid, dapat Anda gunakan pidofdengan || (||) untuk menjalankan perintah jika prosesnya tidak ada dan && untuk menjalankan sesuatu jika prosesnya benar-benar ada, sehingga menciptakan persyaratan if / then / else yang cepat. Misalnya di sini ada satu dengan proses yang berjalan (browser chrome saya, yang nama prosesnya "chrome") dan satu pengujian untuk proses yang tidak ada. Saya menekan output standar menggunakan 1> / dev / null sehingga tidak mencetak:

$ (pidof chrome 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run instea\
d"
its running? ok, so am i then
$ (pidof nosuchprocess 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run\
 instead"
it's not running? ok i'll run instead
$
yuvilio
sumber
1

Tidak ada solusi "sederhana" yang bekerja untuk saya karena biner yang saya perlu periksa tidak diinstal di seluruh sistem, jadi saya harus memeriksa dengan path, yang pada gilirannya memerlukan menggunakan ps -ef | greppendekatan:

app="$_sdir/Logic 1.2.18 (64-bit)/Logic"

app_pid=`ps -ef | grep "$app" | awk '{print $2}'`

if `ps -p $app_pid > /dev/null`; then
    echo "An instance of logic analyzer is appear to be running."
    echo "Not starting another instance."
    exit 5
else
    nohup "$app" &> /dev/null &
fi
ceremcem
sumber
0

Hal pertama yang terlintas di benak saya untuk masalah Anda:
ps aux | grep -i abcakan menunjukkan detail proses jika berjalan. Anda dapat mencocokkan jumlah garis atau waktu untuk menjalankannya dan membandingkannya dengan nol atau manipulasi lainnya. Ketika Anda menjalankan perintah di atas, ia akan menunjukkan kepada Anda setidaknya satu baris output yaitu detail tentang proses yang dibuat oleh perintah grep ini .. Jadi berhati-hatilah.
Itu harus dilakukan sebagai hack sederhana. Masukkan ke dalam skrip bash dan lihat apakah itu membantu.

drake01
sumber
0

Menggunakan start-stop-daemon:

/sbin/start-stop-daemon --background --make-pidfile --pidfile /tmp/foo.pid -S --startas /usr/bin/program -- arg1 arg2

Ini berfungsi sebagai pengguna normal.

Martin Monperrus
sumber
0

Saya menemukan bahwa jawaban yang diterima yang diposting oleh @John Vrbanac tidak bekerja untuk saya, dan bahwa jawaban yang diposting oleh @geirha tidak menjawab pertanyaan awal.

Solusi John Vrbanac tidak bekerja untuk memeriksa apakah proses PHP berjalan atau tidak untuk saya, saya menjalankan CentOS 7.

Jawaban @ geirha hanya memastikan instance belum berjalan sebelum memulai yang lain. Ini bukan pertanyaan asli, pertanyaan asli adalah untuk memeriksa apakah suatu proses sedang berjalan atau tidak.

Inilah yang bekerja untuk saya:

Katakanlah proses saya memiliki string "Jane" dalam nama prosesnya. Ini akan menemukan apakah itu berjalan atau tidak. Ini berfungsi untuk skrip BASH dan PHP.

ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "It's running"
else
    echo "It's not running"
fi
Wayne Workman
sumber
1
Ah, dan ini adalah situs Q&A Ubuntu, tidak mengherankan bahwa beberapa jawaban di sini tidak berfungsi pada CentOS 7 karena Linux di luar topik di sini. Versi lain dari Linux didukung di unix.stackexchange.com
Penatua Geek
walaupun pembuat jawabannya menggunakan CentOS, jawaban ini masih berlaku untuk ubuntu.
Phillip -Zyan K Lee- Stockmann
0
## bash

## function to check if a process is alive and running:

_isRunning() {
    ps -o comm= -C "$1" 2>/dev/null | grep -x "$1" >/dev/null 2>&1
}

## example 1: checking if "gedit" is running

if _isRunning gedit; then
    echo "gedit is running"
else
    echo "gedit is not running"
fi

## example 2: start lxpanel if it is not there

if ! _isRunning lxpanel; then
    lxpanel &
fi

## or

_isRunning lxpanel || (lxpanel &)

Catatan : pgrep -x lxpanelatau pidof lxpanelmasih laporan yang lxpanelberjalan bahkan ketika sudah tidak aktif (zombie); jadi untuk mendapatkan proses yang hidup dan berjalan, kita perlu menggunakan psdangrep

Bach Lien
sumber
-1

Pada 23 September 2016, pgrep tampaknya membutuhkan opsi "-x" agar skrip muru dapat berfungsi.

#!/bin/bash

if pgrep -x "conky" > /dev/null 2>&1
then
  echo "conky running already"
else
  echo "now starting conky"
  conky
fi
exit 0

Saya mencoba dan menguji skrip di atas pada mesin Ubuntu 16.04.1. Nikmati!

dzmanto
sumber
-1
#!/bin/bash
while [ true ]; do     # Endless loop.
  pid=`pgrep -x ${1}`  # Get a pid.
  if [ -z $pid ]; then # If there is none,
    ${1} &             # Start Param to background.
  else
    sleep 60           # Else wait.
  fi
done
pengguna7449824
sumber
1
Selamat Datang di Tanya Ubuntu! Saya sarankan untuk mengedit jawaban ini untuk memperluasnya dengan perincian spesifik tentang apa yang dilakukannya. (Lihat juga Bagaimana cara saya menulis jawaban yang bagus? Untuk saran umum tentang jawaban seperti apa yang dianggap paling berharga di AskUbuntu.)
David Foerster
-3

isProcessRunning () {if [$ (pidof $ 1)> / dev / null]; lalu retval = 'true'; else retval = 'false'; fi; echo $ retval; }

isProcessRunning geany

benar

Dominic
sumber