Linux / Unix perintah untuk menentukan apakah proses sedang berjalan?

97

Saya memerlukan perintah shell / bash platform independen (Linux / Unix | OSX) yang akan menentukan apakah proses tertentu sedang berjalan. misalnya mysqld, httpd... Apa cara / perintah paling sederhana untuk melakukan ini?

Jalan Raya Kehidupan
sumber

Jawaban:

168

Meskipun pidofdan pgrepmerupakan alat yang hebat untuk menentukan apa yang sedang berjalan, sayangnya, keduanya tidak tersedia di beberapa sistem operasi. Aman gagal pasti akan menggunakan yang berikut ini:ps cax | grep command

Output dari Gentoo Linux:

14484? S 0:00 apache2
14667? S 0:00 apache2
19620? Sl 0:00 apache2
21132? Ss 0:04 apache2

Output di OS X:

42582 ?? Z 0: 00.00 (smbclient)
46529 ?? Z 0: 00.00 (smbclient)
46539 ?? Z 0: 00.00 (smbclient)
46547 ?? Z 0: 00.00 (smbclient)
46586 ?? Z 0: 00.00 (smbclient)
46594 ?? Z 0: 00.00 (smbclient)

Di Linux dan OS X, grep mengembalikan kode keluar sehingga mudah untuk memeriksa apakah prosesnya ditemukan atau tidak:

#!/bin/bash
ps cax | grep httpd > /dev/null
if [ $? -eq 0 ]; then
  echo "Process is running."
else
  echo "Process is not running."
fi

Selain itu, jika Anda menginginkan daftar PID, Anda dapat dengan mudah melakukan grep juga:

ps cax | grep httpd | grep -o '^ [] * [0-9] *'

Yang keluarannya sama di Linux dan OS X:

3519 3521 3523 3524

Output dari berikut ini adalah string kosong, membuat pendekatan ini aman untuk proses yang tidak berjalan:

gema ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'

Pendekatan ini cocok untuk menulis pengujian string kosong sederhana, kemudian melakukan iterasi melalui PID yang ditemukan.

#!/bin/bash
PROCESS=$1
PIDS=`ps cax | grep $PROCESS | grep -o '^[ ]*[0-9]*'`
if [ -z "$PIDS" ]; then
  echo "Process not running." 1>&2
  exit 1
else
  for PID in $PIDS; do
    echo $PID
  done
fi

Anda dapat mengujinya dengan menyimpannya ke file (bernama "berjalan") dengan izin eksekusi (chmod + x berjalan) dan mengeksekusinya dengan parameter: ./running "httpd"

#!/bin/bash
ps cax | grep httpd
if [ $? -eq 0 ]; then
  echo "Process is running."
else
  echo "Process is not running."
fi

PERINGATAN!!!

Harap diingat bahwa Anda hanya mengurai output ps axyang berarti, seperti yang terlihat pada output Linux, ini tidak hanya mencocokkan proses, tetapi juga argumen yang diteruskan ke program itu. Saya sangat menyarankan agar sespesifik mungkin saat menggunakan metode ini (misalnya, ./running "mysql"juga akan mencocokkan proses 'mysqld'). Saya sangat merekomendasikan penggunaan whichuntuk memeriksa jalur lengkap jika memungkinkan.


Referensi:

http://linux.about.com/od/commands/l/blcmdl1_ps.htm

http://linux.about.com/od/commands/l/blcmdl1_grep.htm

Caleb Grey
sumber
Prosesnya bisa berjalan, tapi dihentikan. Jadi jika tujuannya adalah untuk menguji apakah mysqld atau httpd "aktif dan berjalan" (merespons), Anda juga harus memeriksa apakah itu dihentikan atau tidak.
oluc
2
Maaf, tetapi sementara jawabannya pasti benar dari sudut pandang semantik, saya sepenuhnya menentang mencoba menemukan proses dengan pencocokan pola pada proses arg vector. Pendekatan semacam itu pasti akan gagal cepat atau lambat (Anda benar-benar mengakuinya sendiri, dengan mengatakan bahwa diperlukan lebih banyak pemeriksaan). Saya telah menambahkan rekomendasi saya sendiri dalam jawaban terpisah.
peterh
6
grepjuga akan menemukan sendiri berjalan (misalnya ps cax | grep randomnameakan selalu kembali 0 karena greptemuan grep randomname(harap ini jelas ...) Satu memperbaiki adalah dengan menambahkan tanda kurung di sekitar huruf pertama dari nama proses, misalnya. ps cax | grep [r]andomname.
Kyle G.
ps cax | rev | cut -f1 -d' ' | revhanya akan menampilkan kolom nama, untuk penguraian yang lebih mudah.
Tyzoid
1
ps caxmungkin tidak menampilkan nama perintah seluruhnya. Misalnya mencetak "chromium-browse" bukan "chromium-browser".
jarno
24

Anda HARUS mengetahui PID!

Menemukan proses dengan mencoba melakukan beberapa jenis pengenalan pola pada argumen proses (seperti pgrep "mysqld") adalah strategi yang pasti akan gagal cepat atau lambat. Bagaimana jika Anda menjalankan dua mysqld? Lupakan pendekatan itu. Anda MUNGKIN melakukannya dengan benar untuk sementara dan MUNGKIN berhasil selama satu atau dua tahun tetapi kemudian terjadi sesuatu yang belum Anda pikirkan.

Hanya proses id (pid) yang benar-benar unik.

Selalu simpan pid saat Anda meluncurkan sesuatu di latar belakang. Di Bash ini dapat dilakukan dengan $!variabel Bash. Anda akan menyelamatkan diri Anda dari begitu banyak masalah dengan melakukannya.

Cara menentukan apakah proses sedang berjalan (oleh pid)

Jadi sekarang pertanyaannya menjadi bagaimana mengetahui apakah pid sedang berjalan.

Cukup lakukan:

ps -o pid = -p <pid>

Ini adalah POSIX dan karenanya portabel. Ini akan mengembalikan pid itu sendiri jika proses sedang berjalan atau tidak mengembalikan apa-apa jika proses tidak berjalan. Sebenarnya perintah akan mengembalikan satu kolom, itu pid, tetapi karena kita telah memberikan judul judul yang kosong (hal-hal tepat sebelum tanda sama dengan) dan ini adalah satu-satunya kolom yang diminta maka perintah ps tidak akan menggunakan header sama sekali. Itulah yang kami inginkan karena mempermudah penguraian.

Ini akan berfungsi di Linux, BSD, Solaris, dll.

Strategi lain adalah menguji nilai keluar dari psperintah di atas . Ini harus nol jika proses sedang berjalan dan bukan nol jika tidak. Spesifikasi POSIX mengatakan bahwa psharus keluar> 0 jika telah terjadi kesalahan tetapi tidak jelas bagi saya apa yang dimaksud dengan 'kesalahan'. Oleh karena itu saya secara pribadi tidak menggunakan strategi itu meskipun saya cukup yakin itu akan bekerja dengan baik di semua platform Unix / Linux.

peterh
sumber
1
Kecuali ini tidak menjawab pertanyaan, yaitu untuk menentukan apakah suatu layanan sedang berjalan. PID tidak akan diketahui dalam kasus tersebut, karena jawaban ini hanya berlaku jika Anda melakukan tahu PID.
Highway of Life
2
Salah. Inti dari komentar saya adalah untuk mengambil langkah mundur dan mengatakan bahwa jika Anda pertama kali menemukan diri Anda dalam situasi di mana Anda harus melakukan beberapa bentuk grep <sometext>untuk menemukan proses yang diberikan maka Anda telah melakukan sesuatu yang salah ketika Anda memulai proses tersebut, IMHO. Saya mengambil dari pertanyaan OP bahwa memang dia memiliki kendali atas bagaimana proses itu dimulai.
peterh
2
"Istilah" yang lebih tepat untuk pertanyaan OP seharusnya adalah "perintah lintas platform untuk menentukan apakah suatu layanan sedang berjalan", ini bukan sistem yang sama yang menjalankan pemeriksaan, tetapi sistem luar, jadi PID tidak akan menjadi dikenal sama sekali.
Highway of Life
2
Ini tidak mudah. Proses yang Anda minati mungkin telah mati setelah sistem berjalan cukup lama sehingga PID dapat dibungkus, dan proses lain mungkin telah dialokasikan ke PID yang sama yang Anda periksa. stackoverflow.com/questions/11323410/linux-pid-recycling
claymation
1
@keluarga. Poin yang adil. Namun metode PID masih lebih baik daripada pencocokan pola pada argumen proses karena bentrokan PID jauh lebih tidak mungkin daripada mengatakan secara tidak sengaja memulai dua contoh layanan yang sama. Hanya dua sen saya. :-)
peterh
15

Di sebagian besar distribusi Linux, Anda dapat menggunakan pidof(8).

Ini akan mencetak id proses dari semua contoh yang berjalan dari proses tertentu, atau tidak sama sekali jika tidak ada contoh yang berjalan.

Misalnya, di sistem saya (saya memiliki empat contoh bashdan satu contoh remminaberjalan):

$ pidof bash remmina
6148 6147 6144 5603 21598

Di Unix lain, pgrepatau kombinasi dari psdan grepakan mencapai hal yang sama, seperti yang dinyatakan dengan benar oleh pihak lain.

Frédéric Hamidi
sumber
+1 pidof httpdberfungsi dengan baik di Red Hat 5. Tetapi di Red Hat 4 saya, pidoftidak ada :-(
olibre
Memang, perintah ini kurang tersebar dari yang saya kira, saya mengedit jawaban saya untuk memperjelas ini.
Frédéric Hamidi
Jawaban bersih yang bagus memang. (pada sistem yang didukung). Terima kasih.
Mtl Dev
7

Ini akan bekerja pada kebanyakan jenis Unix, BSD dan Linux:

PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep

Diuji pada:

  • SunOS 5.10 [Oleh karena itu PATH=...]
  • Linux 2.6.32 (CentOS)
  • Linux 3.0.0 (Ubuntu)
  • Darwin 11.2.0
  • FreeBSD 9.0-STABLE
  • Red Hat Enterprise Linux ES rilis 4
  • Red Hat Enterprise Linux Server rilis 5
Johnsyweb
sumber
2
+1 Ya sederhana ps. Untuk menghindari yang kedua grepsaya sarankan:ps aux | grep [h]ttpd
olibre
Saya tidak menggunakan trik kurung siku di sini untuk membuatnya lebih mudah menempatkan variabel ke dalam utama grep.
Johnsyweb
1
Baiklah;) Saya baru saja menguji Red Hat AS 4 dan Red Hat AP 5. Tentu saja saya bekerja! Jadi Anda dapat menambahkan dalam daftar: Red Hat Enterprise Linux ES rilis 4 dan Red Hat Enterprise Linux Server rilis 5 . Cheers
olibre
@Downvoter: Mengapa? Apa yang saya lewatkan? Sejauh yang saya tahu, jawaban yang diterima adalah melakukan pencarian yang sama!
Johnsyweb
6

Cara termudah adalah dengan menggunakan ps dan grep:

command="httpd"
running=`ps ax | grep -v grep | grep $command | wc -l`
if [ running -gt 0 ]; then
    echo "Command is running"
else
    echo "Command is not running"
fi

Jika perintah Anda memiliki beberapa argumen perintah, Anda juga dapat meletakkan lebih banyak 'grep cmd_arg1' setelah 'grep $ command' untuk menyaring proses lain yang mungkin Anda tidak tertarik.

Contoh: tunjukkan jika ada proses java dengan argumen yang diberikan:

-Djava.util.logging.config.file = logging.properties

sedang berlari

ps ax | grep -v grep | grep java | grep java.util.logging.config.file=logging.properties | wc -l
Pawel Solarski
sumber
2
Sebenarnya, menggunakan ps caxmenghilangkan kebutuhan untuk menggunakan grep -v. Jadi misalnya, Anda dapat menggunakan: ps cax | grep java > /dev/null || echo "Java not running".
Highway of Life
1
Ada kesalahan di baris ke-3. harap ubah "berjalan" menjadi "$ berjalan".
Programmer
5

Hanya sedikit tambahan: jika Anda menambahkan -cflag ke ps, Anda tidak perlu menghapus baris yang berisi proses grep grep -vsesudahnya. Yaitu

ps acux | grep cron

adalah semua pengetikan yang Anda perlukan pada sistem bsd-ish (ini termasuk MacOSX). Anda dapat meninggalkannya -ujika Anda membutuhkan lebih sedikit informasi.

Pada sistem di mana genetika dari psperintah asli mengarah kembali ke SysV, Anda akan menggunakan

ps -e |grep cron

atau

ps -el |grep cron 

untuk daftar yang berisi lebih dari sekedar pid dan nama proses. Tentu saja Anda dapat memilih bidang tertentu untuk dicetak menggunakan -o <field,field,...>opsi tersebut.

Tatjana Heuser
sumber
Bagaimana jawaban ini portabel? (Anda mengatakan bahwa berbagai bentuk perintah ps harus digunakan pada platform yang berbeda)
peterh
ps sayangnya adalah salah satu alat dengan serangkaian opsi berbeda untuk hasil yang sama tergantung pada leluhurnya. Jadi, kecuali Anda menulis bungkus Anda sendiri (sekali lagi tidak kompatibel dengan hal lain) di sekitar ini, cara yang harus dilakukan adalah mengetahui garis utama warisan dan menyesuaikannya dengan itu. Ini berbeda ketika Anda membuat skrip - di sana Anda akan menggunakan perbedaan ini untuk menentukan cabang mana Anda berada dan menyesuaikan perilaku skrip Anda. Intinya: Anda harus mengetahui keduanya. Contoh terkenal: skrip "configure" dari Larry Wall. Kutipan terkenal: Selamat, Anda tidak menjalankan Eunice.
Tatjana Heuser
5

Dengan menggabungkan berbagai saran bersama-sama, versi terbersih yang dapat saya hasilkan (tanpa grep yang tidak dapat diandalkan yang memicu bagian kata) adalah:

kill -0 $(pidof mysql) 2> /dev/null || echo "Mysql ain't runnin' message/actions"

kill -0 tidak mematikan proses tetapi memeriksa apakah itu ada dan kemudian mengembalikan true, jika Anda tidak memiliki pidof di sistem Anda, simpan pid ketika Anda meluncurkan proses:

$ mysql &
$ echo $! > pid_stored

lalu di script:

kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
gletscher
sumber
3

Saya menggunakan pgrep -l httpdtetapi tidak yakin itu ada di platform apa pun ...
Siapa yang dapat mengonfirmasi di OSX?

olibre.dll
sumber
Terima kasih @Johnsyweb. Bisakah Anda juga memeriksanya pidof? Oke, Anda melakukannya. Terima kasih. Jadi kita harus menemukan sesuatu yang lain yang bekerja di OSX ... Dasar Anda ps|grepmungkin satu-satunya solusi ;-)
olibre
1

Anda harus mengetahui PID dari proses Anda.

Saat Anda meluncurkannya, PID-nya akan dicatat dalam $!variabel. Simpan PID ini ke dalam file.

Kemudian Anda perlu memeriksa apakah PID ini sesuai dengan proses yang sedang berjalan. Berikut skrip kerangka lengkapnya:

FILE="/tmp/myapp.pid"

if [ -f $FILE ];
then
   PID=$(cat $FILE)
else
   PID=1
fi

ps -o pid= -p $PID
if [ $? -eq 0 ]; then
  echo "Process already running."  
else
  echo "Starting process."
  run_my_app &
  echo $! > $FILE
fi

Berdasarkan jawaban dari peterh. Trik untuk mengetahui apakah PID tertentu sedang berjalan ada dalam ps -o pid= -p $PIDinstruksi.

icarito
sumber
0

Pendekatan ini dapat digunakan jika perintah 'ps', 'pidof' dan sisanya tidak tersedia. Saya pribadi sangat sering menggunakan procfs di alat / skrip / program saya.

   egrep -m1  "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3

Sedikit penjelasan apa yang sedang terjadi:

  1. -m1 - hentikan proses pada pertandingan pertama
  2. "mysqld $ | httpd $" - grep akan mencocokkan baris yang diakhiri dengan mysqld ATAU httpd
  3. / proc / [0-9] * - bash akan mencocokkan baris yang dimulai dengan angka apa pun
  4. cut - cukup pisahkan output dengan pembatas '/' dan ekstrak bidang 3
Tom Lime
sumber
0

Ini mencetak jumlah proses yang nama dasarnya adalah "chromium-browser":

ps -e -o args= | awk 'BEGIN{c=0}{
 if(!match($1,/^\[.*\]$/)){sub(".*/","",$1)} # Do not strip process names enclosed by square brackets.
 if($1==cmd){c++}
}END{print c}' cmd="chromium-browser"

Jika ini mencetak "0", proses tidak berjalan. Perintah mengasumsikan jalur proses tidak berisi ruang putus. Saya belum menguji ini dengan proses yang ditangguhkan atau proses zombie.

Diuji menggunakan gwaksebagai awkalternatif di Linux.

Berikut adalah solusi yang lebih serbaguna dengan beberapa contoh penggunaan:

#!/bin/sh
isProcessRunning() {
if [ "${1-}" = "-q" ]; then
 local quiet=1;
 shift
else
 local quiet=0;
fi
ps -e -o pid,args= | awk 'BEGIN{status=1}{
 name=$2
 if(name !~ /^\[.*\]$/){sub(".*/","",name)} # strip dirname, if process name is not enclosed by square brackets.
 if(name==cmd){status=0; if(q){exit}else{print $0}}
}END{exit status}' cmd="$1" q=$quiet
}

process='chromium-browser'

printf "Process \"${process}\" is "
if isProcessRunning -q "$process" 
 then printf "running.\n"
 else printf "not running.\n"; fi

printf "Listing of matching processes (PID and process name with command line arguments):\n"
isProcessRunning "$process"
jarno
sumber
0

Ini versi saya. Fitur:

  • memeriksa nama program yang tepat (argumen pertama fungsi). pencarian untuk "mysql" tidak akan cocok dengan "mysqld" yang sedang berjalan
  • mencari argumen program (argumen kedua dari fungsi)

naskah:

#!/bin/bash

# $1 - cmd
# $2 - args
# return: 0 - no error, running; 1 - error, not running
function isRunning() {
    for i in $(pidof $1); do
        cat /proc/$i/cmdline | tr '\000' ' ' | grep -F -e "$2" 1>&2> /dev/null
        if [ $? -eq 0 ]; then
            return 0
        fi
    done
    return 1
}

isRunning java "-Djava.util.logging.config.file=logging.properties"
if [ $? -ne 0 ]; then
    echo "not running, starting..."
fi
Raigedas
sumber
0

Tidak ada jawaban yang berhasil untuk saya, jadi inilah jawaban saya:

process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
  echo "Process is not running."
else
  echo "Process is running."
fi

Penjelasan:

|tr -d '\n'

Ini menghapus carriage return yang dibuat oleh terminal. Selebihnya bisa dijelaskan melalui postingan ini .

Jeff Luyet
sumber
-1

Fungsi shell berikut, yang hanya berdasarkan perintah standar POSIX dan opsi harus bekerja pada sebagian besar (jika tidak ada) sistem Unix dan linux. :

isPidRunning() {
  cmd=`
    PATH=\`getconf PATH\` export PATH
    ps -e -o pid= -o comm= |
      awk '$2 ~ "^.*/'"$1"'$" || $2 ~ "^'"$1"'$" {print $1,$2}'
  `
  [ -n "$cmd" ] &&
    printf "%s is running\n%s\n\n" "$1" "$cmd" ||
    printf "%s is not running\n\n" $1
  [ -n "$cmd" ]
}

$ isPidRunning httpd
httpd is running
586 /usr/apache/bin/httpd
588 /usr/apache/bin/httpd

$ isPidRunning ksh
ksh is running
5230 ksh

$ isPidRunning bash
bash is not running

Perhatikan bahwa ini akan tersedak ketika diberikan nama perintah "0]" yang meragukan dan juga akan gagal untuk mengidentifikasi proses yang memiliki ruang tersemat di namanya.

Perhatikan juga bahwa solusi yang paling disukai dan diterima menuntut psopsi non-portabel dan secara serampangan menggunakan shell yang, terlepas dari popularitasnya, tidak dijamin akan ada di setiap mesin Unix / Linux ( bash)

jlliagre.dll
sumber
$ isPidRunning 0]mencetak misalnya "0] sedang menjalankan 3 [ksoftirqd / 0] 8 [rcuop / 0] 17 [rcuos / 0] 26 [rcuob / 0] 34 [migrasi / 0] 35 [pengawas / 0]" di sini.
jarno
Untuk apa Anda membutuhkan benda PATH itu?
jarno
Saya mengembangkan solusi lebih lanjut di sini .
jarno
@jarno Pengaturan PATH adalah persyaratan agar skrip menjadi portabel. Jika tidak, itu akan gagal setidaknya pada Solaris 10 dan yang lebih lama dan mungkin implementasi Unix lainnya.
jlliagre
1
@ JARNO Saya mungkin melakukannya tetapi perlu mengulang pengaturan PATH ini untuk awk juga. Perhatikan bahwa saya kembali ke sintaks backtick lama menjadi portabel dengan shell bourne sintaks pra-POSIX.
jlliagre