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?
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?
Jawaban:
Meskipun pidof
dan pgrep
merupakan 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 ax
yang 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 which
untuk memeriksa jalur lengkap jika memungkinkan.
Referensi:
grep
juga akan menemukan sendiri berjalan (misalnya ps cax | grep randomname
akan selalu kembali 0 karena grep
temuan 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
.
ps cax | rev | cut -f1 -d' ' | rev
hanya akan menampilkan kolom nama, untuk penguraian yang lebih mudah.
ps cax
mungkin tidak menampilkan nama perintah seluruhnya. Misalnya mencetak "chromium-browse" bukan "chromium-browser".
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.
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 ps
perintah di atas . Ini harus nol jika proses sedang berjalan dan bukan nol jika tidak. Spesifikasi POSIX mengatakan bahwa ps
harus 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.
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.
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 bash
dan satu contoh remmina
berjalan):
$ pidof bash remmina
6148 6147 6144 5603 21598
Di Unix lain, pgrep
atau kombinasi dari ps
dan grep
akan mencapai hal yang sama, seperti yang dinyatakan dengan benar oleh pihak lain.
pidof httpd
berfungsi dengan baik di Red Hat 5. Tetapi di Red Hat 4 saya, pidof
tidak ada :-(
Ini akan bekerja pada kebanyakan jenis Unix, BSD dan Linux:
PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
Diuji pada:
PATH=...
]ps
. Untuk menghindari yang kedua grep
saya sarankan:ps aux | grep [h]ttpd
grep
.
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
ps cax
menghilangkan kebutuhan untuk menggunakan grep -v
. Jadi misalnya, Anda dapat menggunakan: ps cax | grep java > /dev/null || echo "Java not running"
.
Hanya sedikit tambahan: jika Anda menambahkan -c
flag ke ps, Anda tidak perlu menghapus baris yang berisi proses grep grep -v
sesudahnya. Yaitu
ps acux | grep cron
adalah semua pengetikan yang Anda perlukan pada sistem bsd-ish (ini termasuk MacOSX). Anda dapat meninggalkannya -u
jika Anda membutuhkan lebih sedikit informasi.
Pada sistem di mana genetika dari ps
perintah 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.
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"
Saya menggunakan pgrep -l httpd
tetapi tidak yakin itu ada di platform apa pun ...
Siapa yang dapat mengonfirmasi di OSX?
pidof
? Oke, Anda melakukannya. Terima kasih. Jadi kita harus menemukan sesuatu yang lain yang bekerja di OSX ... Dasar Anda ps|grep
mungkin satu-satunya solusi ;-)
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 $PID
instruksi.
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:
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 gwak
sebagai awk
alternatif 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"
Ini versi saya. Fitur:
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
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 .
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 ps
opsi non-portabel dan secara serampangan menggunakan shell yang, terlepas dari popularitasnya, tidak dijamin akan ada di setiap mesin Unix / Linux ( bash
)
$ 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.