Tôi cần một lệnh shell / bash độc lập với nền tảng (Linux / Unix | OSX) sẽ xác định xem một quy trình cụ thể có đang chạy hay không. ví dụ mysqld
, httpd
... Cách / lệnh đơn giản nhất để thực hiện việc này là gì?
Tôi cần một lệnh shell / bash độc lập với nền tảng (Linux / Unix | OSX) sẽ xác định xem một quy trình cụ thể có đang chạy hay không. ví dụ mysqld
, httpd
... Cách / lệnh đơn giản nhất để thực hiện việc này là gì?
Câu trả lời:
Mặc dù pidof
và pgrep
là những công cụ tuyệt vời để xác định những gì đang chạy, nhưng thật không may, cả hai đều không khả dụng trên một số hệ điều hành. Một két an toàn hỏng chắc chắn sẽ được sử dụng như sau:ps cax | grep command
Đầu ra trên Gentoo Linux:
14484? S 0:00 apache2 14667? S 0:00 apache2 Năm 19620? Sl 0:00 apache2 21132? Ss 0:04 apache2
Đầu ra trên 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)
Trên cả Linux và OS X, grep trả về mã thoát để dễ dàng kiểm tra xem quá trình có được tìm thấy hay không:
#!/bin/bash
ps cax | grep httpd > /dev/null
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running."
fi
Hơn nữa, nếu bạn muốn có danh sách các PID, bạn cũng có thể dễ dàng tìm kiếm các PID đó:
ps cax | grep httpd | grep -o '^ [] * [0-9] *'
Đầu ra của ai giống nhau trên Linux và OS X:
3519 3521 3523 3524
Đầu ra của phần sau là một chuỗi trống, làm cho cách tiếp cận này an toàn cho các quá trình không chạy:
tiếng vang ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'
Cách tiếp cận này phù hợp để viết một bài kiểm tra chuỗi rỗng đơn giản, sau đó thậm chí lặp lại qua các PID đã phát hiện.
#!/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
Bạn có thể kiểm tra nó bằng cách lưu nó vào một tệp (có tên "đang chạy") với quyền thực thi (chmod + x đang chạy) và thực thi nó với một tham số: ./running "httpd"
#!/bin/bash
ps cax | grep httpd
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running."
fi
CẢNH BÁO!!!
Xin lưu ý rằng bạn chỉ đơn giản là phân tích cú pháp đầu ra ps ax
có nghĩa là, như đã thấy trong đầu ra của Linux, nó không chỉ khớp trên các quy trình mà còn cả các đối số được chuyển đến chương trình đó. Tôi thực sự khuyên bạn nên càng cụ thể càng tốt khi sử dụng phương pháp này (ví dụ: ./running "mysql"
cũng sẽ khớp với các quy trình 'mysqld'). Tôi thực sự khuyên bạn nên sử dụng which
để kiểm tra một đường dẫn đầy đủ nếu có thể.
Người giới thiệu:
grep
cũng sẽ tìm thấy bản thân đang chạy (ví dụ như ps cax | grep randomname
sẽ luôn luôn trở về 0 vì grep
phát hiện grep randomname
(hy vọng điều này là rõ ràng ...) Một sửa chữa là thêm dấu ngoặc vuông xung quanh chữ cái đầu tiên của tên quá trình, ví dụ như. ps cax | grep [r]andomname
.
ps cax | rev | cut -f1 -d' ' | rev
sẽ chỉ hiển thị cột tên để phân tích cú pháp dễ dàng hơn.
ps cax
có thể không xuất hoàn toàn tên lệnh. Ví dụ: nó in "chromium-Browse" thay vì "chromium-browser".
Tìm kiếm một quy trình bằng cách cố gắng thực hiện một số kiểu nhận dạng mẫu trên các đối số của quy trình (như pgrep "mysqld"
) là một chiến lược sớm muộn cũng thất bại. Điều gì sẽ xảy ra nếu bạn có hai mysqld đang chạy? Quên cách tiếp cận đó. Bạn CÓ THỂ làm nó đúng tạm thời và nó CÓ THỂ hoạt động trong một hoặc hai năm nhưng sau đó sẽ có điều gì đó xảy ra mà bạn chưa nghĩ đến.
Chỉ có id quy trình (pid) là thực sự duy nhất.
Luôn lưu trữ pid khi bạn khởi chạy thứ gì đó trong nền. Trong Bash, điều này có thể được thực hiện với $!
biến Bash. Bạn sẽ tiết kiệm cho mình rất nhiều rắc rối bằng cách làm như vậy.
Vì vậy, bây giờ câu hỏi trở thành làm thế nào để biết nếu một pid đang chạy.
Đơn giản chỉ cần làm:
ps -o pid = -p <pid>
Đây là POSIX và do đó có thể di động. Nó sẽ tự trả về pid nếu quá trình đang chạy hoặc không trả về gì nếu quá trình không chạy. Nói một cách chính xác thì lệnh sẽ trả về một cột duy nhất pid
, nhưng vì chúng ta đã cho rằng một tiêu đề tiêu đề trống (thứ nằm ngay trước dấu bằng) và đây là cột duy nhất được yêu cầu nên lệnh ps sẽ không sử dụng tiêu đề. Đó là những gì chúng tôi muốn vì nó giúp phân tích cú pháp dễ dàng hơn.
Điều này sẽ hoạt động trên Linux, BSD, Solaris, v.v.
Một chiến lược khác sẽ là kiểm tra giá trị thoát từ ps
lệnh trên . Nó phải bằng 0 nếu quá trình đang chạy và khác 0 nếu không. Thông số kỹ thuật POSIX nói rằng ps
phải thoát> 0 nếu có lỗi xảy ra nhưng tôi không rõ điều gì tạo thành 'lỗi'. Vì vậy, cá nhân tôi không sử dụng chiến lược đó mặc dù tôi khá chắc chắn rằng nó sẽ hoạt động tốt trên tất cả các nền tảng Unix / Linux.
grep <sometext>
để tìm một quy trình nhất định thì bạn đã làm sai khi bắt đầu quy trình, IMHO. Tôi lấy nó từ câu hỏi của OP rằng thực sự anh ta có quyền kiểm soát cách thức bắt đầu quá trình.
Trên hầu hết các bản phân phối Linux, bạn có thể sử dụng pidof
(8).
Nó sẽ in id quy trình của tất cả các phiên bản đang chạy của các quy trình được chỉ định, hoặc không in gì nếu không có phiên bản nào đang chạy.
Ví dụ: trên hệ thống của tôi (tôi có bốn phiên bản bash
và một phiên bản remmina
đang chạy):
$ pidof bash remmina
6148 6147 6144 5603 21598
Trên các Liên minh khác, pgrep
hoặc sự kết hợp của ps
và grep
sẽ đạt được điều tương tự, như những người khác đã chỉ ra một cách đúng đắn.
pidof httpd
hoạt động tốt trên Red Hat 5. Nhưng trên Red Hat 4 của tôi, pidof
không có mặt :-(
Điều này sẽ hoạt động trên hầu hết các phiên bản Unix, BSD và Linux:
PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
Đã thử nghiệm trên:
PATH=...
]ps
. Để tránh thứ hai grep
tôi đề nghị:ps aux | grep [h]ttpd
grep
.
Cách đơn giản nhất là sử dụng ps và 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
Nếu lệnh của bạn có một số đối số lệnh, thì bạn cũng có thể đặt thêm 'grep cmd_arg1' sau 'grep $ command' để lọc ra các quy trình có thể có khác mà bạn không quan tâm.
Ví dụ: chỉ cho tôi nếu có bất kỳ quy trình java nào với đối số được cung cấp:
-Djava.util.logging.config.file = logging.properties
đang chạy
ps ax | grep -v grep | grep java | grep java.util.logging.config.file=logging.properties | wc -l
ps cax
loại bỏ nhu cầu sử dụng grep -v
. Vì vậy, ví dụ, bạn có thể sử dụng: ps cax | grep java > /dev/null || echo "Java not running"
.
Chỉ là một bổ sung nhỏ: nếu bạn thêm -c
cờ vào ps, bạn không cần phải xóa dòng chứa quá trình grep grep -v
sau đó. I E
ps acux | grep cron
là tất cả những gì bạn cần nhập trên hệ thống bsd-ish (điều này bao gồm cả MacOSX) Bạn có thể bỏ -u
đi nếu bạn cần ít thông tin hơn.
Trên một hệ thống mà di truyền của ps
lệnh gốc trỏ về SysV, bạn sẽ sử dụng
ps -e |grep cron
hoặc là
ps -el |grep cron
cho một danh sách không chỉ có pid và tên tiến trình. Tất nhiên, bạn có thể chọn các trường cụ thể để in ra bằng cách sử dụng -o <field,field,...>
tùy chọn.
Kết hợp các đề xuất khác nhau lại với nhau, phiên bản rõ ràng nhất mà tôi có thể đưa ra (không có grep không đáng tin cậy kích hoạt các phần của từ) là:
kill -0 $(pidof mysql) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
kill -0 không giết quá trình nhưng kiểm tra nếu nó tồn tại và sau đó trả về true, nếu bạn không có pidof trên hệ thống của mình, hãy lưu trữ pid khi bạn khởi chạy quá trình:
$ mysql &
$ echo $! > pid_stored
thì trong script:
kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
Tôi sử dụng pgrep -l httpd
nhưng không chắc nó có trên nền tảng nào ...
Ai có thể xác nhận trên OSX?
pidof
không? OK, bạn đã làm. Cảm ơn bạn. Vì vậy, chúng ta nên tìm một thứ gì đó khác hoạt động trên OSX ... Cơ bản của bạn ps|grep
có thể là giải pháp duy nhất ;-)
Khi bạn khởi chạy nó, PID của nó sẽ được ghi lại trong $!
biến. Lưu PID này vào một tệp.
Sau đó, bạn sẽ cần kiểm tra xem PID này có tương ứng với một quy trình đang chạy hay không. Đây là một tập lệnh sườn hoàn chỉnh:
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
Dựa trên câu trả lời của peterh
. Mẹo để biết liệu một PID nhất định có đang chạy hay không là trong ps -o pid= -p $PID
hướng dẫn.
Cách tiếp cận này có thể được sử dụng trong trường hợp lệnh 'ps', 'pidof' và phần còn lại không khả dụng. Cá nhân tôi sử dụng procfs rất thường xuyên trong các công cụ / tập lệnh / chương trình của mình.
egrep -m1 "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3
Giải thích nhỏ về những gì đang xảy ra:
Điều này in ra số lượng quy trình có tên cơ sở là "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"
Nếu điều này in ra "0", quá trình này không chạy. Lệnh giả định đường dẫn tiến trình không chứa khoảng trắng. Tôi chưa thử nghiệm điều này với các quy trình bị treo hoặc quy trình zombie.
Thử nghiệm sử dụng gwak
như awk
thay thế trong Linux.
Đây là một giải pháp linh hoạt hơn với một số ví dụ sử dụng:
#!/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"
Đây là phiên bản của tôi. Đặc trưng:
kịch bản:
#!/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
Không có câu trả lời nào phù hợp với tôi, vì vậy câu trả lời của tôi:
process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
echo "Process is not running."
else
echo "Process is running."
fi
Giải trình:
|tr -d '\n'
Thao tác này loại bỏ ký tự xuống dòng được tạo bởi terminal. Phần còn lại có thể được giải thích bởi bài đăng này .
Hàm shell sau đây, chỉ dựa trên các lệnh và tùy chọn tiêu chuẩn POSIX nên hoạt động trên hầu hết (nếu không có) hệ thống Unix và 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
Lưu ý rằng nó sẽ bị nghẹt thở khi truyền tên lệnh "0]" đáng ngờ và cũng sẽ không xác định được các quy trình có khoảng trắng nhúng trong tên của chúng.
Cũng xin lưu ý rằng giải pháp được nhiều người ủng hộ và chấp nhận nhất yêu cầu các ps
tùy chọn không di động và sử dụng vô cớ một trình bao mặc dù phổ biến nhưng không được đảm bảo có mặt trên mọi máy Unix / Linux ( bash
)
$ isPidRunning 0]
bản in ví dụ "0] đang chạy 3 [ksoftirqd / 0] 8 [rcuop / 0] 17 [rcuos / 0] 26 [rcuob / 0] 34 [igration / 0] 35 [watchdog / 0]" tại đây.