2009-11-30 35 views
18

Làm cách nào để kiểm tra xem một quá trình trên Mac OS X có đang chạy bằng tên của quy trình trong tập lệnh Bash không?Kiểm tra xem quá trình Mac có đang chạy bằng Bash theo tên quy trình

Tôi đang cố gắng viết một tập lệnh Bash sẽ khởi động lại một quá trình nếu nó đã dừng nhưng không làm gì nếu nó vẫn đang chạy.

+0

Tôi đang thêm "unix" vào danh sách thẻ vì thực sự không có gì cụ thể về câu hỏi này ... (Rời "mac" để mọi người cụ thể tìm thấy nó cũng ...) –

+0

BTW, nếu bạn đang tạo một quy trình giống như daemon trên OS X, bạn nên xem 'launchd', thay thế của Apple cho 'cron',' init', 'inetd' et al. Nó có nhiều tùy chọn để bắt đầu và khởi động lại quy trình trong các ngữ cảnh và thời gian khác nhau. Xem 'man launchd',' man launchd.plist' và google cho nhiều tài liệu và hướng dẫn khác nhau. –

+0

Cảm ơn Ned. Tôi thực sự sử dụng Lingon như một giao diện thân thiện với người dùng để 'launchd'. –

Trả lời

25

Phân tích này:

ps aux | grep [-i] $ProcessName | wc -l 

... có lẽ là lựa chọn tốt nhất của bạn. Dưới đây là một kịch bản ngắn mà những gì bạn đang sau:

#!/bin/bash 
PROCESS=myapp 
number=$(ps aux | grep $PROCESS | wc -l) 

if [ $number -gt 0 ] 
    then 
     echo Running; 
fi 

EDIT: tôi ban đầu bao gồm một lá cờ -i để grep để làm cho nó phân biệt dạng chữ; Tôi đã làm điều này vì chương trình mẫu tôi đã thử là python, mà trên Mac OS X chạy dưới dạng Python - nếu bạn biết chính xác trường hợp của ứng dụng, thì không cần thiết phải -i.

Lợi thế của cách tiếp cận này là quy mô với bạn - trong tương lai, nếu bạn cần đảm bảo rằng, năm phiên bản ứng dụng của bạn đang chạy, bạn đã đếm. Lời nhắc duy nhất là nếu một ứng dụng khác có tên chương trình của bạn trong dòng lệnh của nó, nó có thể xuất hiện - biểu thức chính quy đến grep sẽ giải quyết vấn đề đó, nếu bạn xảo quyệt (và chạy vào điều này).

Nghiên cứu trang người dùng Darwin cho ps, grepwc.

+16

Cảm ơn. Điều này làm việc với một ngoại lệ: nó phải là '-gt 1' chứ không phải là' 0', vì lệnh 'grep' từ bản thân tập lệnh Bash được tính là một trong các dòng trong' ps aux', ít nhất là trong kiểm tra sơ bộ. –

+11

Tôi muốn thêm 'grep -v grep' vào đường dẫn trước' wc'. Bằng cách đó, lệnh grep bị loại trừ khỏi số kết quả phù hợp được tìm thấy. – Jacob

+0

Ứng dụng có hoạt động với tên tệp và đường dẫn thực sự dài không? Đặc biệt là nếu chúng tương tự trong đầu ?, ví dụ. my-long-filename-that-is-really-stupid-of-file-1, tên tập tin dài của tôi-đó-là-thực sự-ngu ngốc-of-file-2 ... Tôi đặt cược nó không, tại ít nhất là không trên cả Linux và Mac OS X, sử dụng cùng một đối số cho ps ... –

10

Một cách khác là sử dụng (lạm dụng?) Tuỳ chọn -d của lệnh killall. Các tùy chọn -d sẽ không thực sự giết quá trình, nhưng thay vào đó in những gì sẽ được thực hiện. Nó cũng sẽ thoát với trạng thái 0 nếu nó tìm thấy một quá trình phù hợp hoặc 1 nếu không. Đặt cùng nhau:

#!/bin/bash 
`/usr/bin/killall -d "$1" &> /dev/null` 
let "RUNNING = ! $?"  # this simply does a boolean 'not' on the return code 
echo $RUNNING 

Để cấp tín dụng khi đến hạn, ban đầu tôi đã lấy kỹ thuật này từ tập lệnh trong trình cài đặt iTunes.

+0

EWW. Tôi sẽ không -1 bởi vì tôi nghĩ rằng chỉ nên được sử dụng cho câu trả lời không chính xác hoặc không phù hợp, nhưng wow. Tại sao làm điều đó khi bạn có thể sử dụng ps và grep? đặc biệt là kể từ khi tôi khá chắc chắn rằng bằng cách sử dụng ps và grep là chính xác những gì killall hiện ... –

+3

Trên thực tế killall là một chút thông minh hơn 'ps | grep '. Nếu bạn chỉ cần grep đầu ra của ps, bạn có thể nhận được dương tính giả. Bị truy nã, nhưng nói rằng quá trình của bạn được đặt tên là 'Thư viện'. 'ps waux | grep Library 'sẽ khớp với rất nhiều thứ trên máy Mac. Phương pháp killall, trong khi một chút wacky tôi thừa nhận, sẽ chỉ phù hợp với một quá trình thực tế có tên là 'Thư viện'. – amrox

+0

Tôi rất tiếc nhưng bạn đang sử dụng hệ thống nào? Tôi không thấy tùy chọn -d trong lệnh killall. http://linux.die.net/man/1/killall – sobi3ch

0

Mac có pidof không? ...

if pidof $processname >/dev/null ; then echo $processname is running ; fi 
+1

Không, thật không may. – amrox

0

Nó có chắc chắn!

pgrep, pkill và pfind cho OpenBSD và Darwin (Mac OS X)

http://proctools.sourceforge.net

(cũng có sẵn thông qua MacPorts: proctools thông tin cổng)

pidof bởi nightproductions.net

+0

Công cụ tuyệt vời, nhưng không phải là tiêu chuẩn. Đôi khi nó là tốt hơn để giải quyết vấn đề này chỉ bằng cách sử dụng các công cụ tiêu chuẩn, đôi khi không! –

2

Tôi thiếu danh tiếng để nhận xét về câu trả lời killall ở trên, nhưng có killall -s để làm điều đó mà không gửi bất kỳ tín hiệu nào:

killall -s "$PROCESSNAME" &> /dev/null 
if [ $? -eq 0 ]; then 
    echo "$PROCESSNAME is running" 
    # if you also need the PID: 
    PID=`killall -s "$PROCESSNAME" | awk '{print $3}'` 
    echo "it's PID is $PID" 
fi 
4

Lệnh đơn giản này sẽ thực hiện thủ thuật. Các dấu ngoặc xung quanh tên quy trình ngăn lệnh grep hiển thị trong danh sách quy trình. Lưu ý không có dấu cách sau dấu phẩy.Có thể có một số vấn đề tính di động như ps trên một số hệ thống unix có thể yêu cầu một chút trước khi lựa chọn:

ps axo pid,command | grep "[S]kype" 

Ưu điểm là bạn có thể sử dụng các kết quả trong một câu lệnh if như thế này:'

if [[ ! $(ps axo pid,command | grep "[i]Tunes.app") ]]; then 
    open -a iTunes 
fi 

Hoặc nếu bạn thích phong cách này:

[[ ! $(ps axo pid,command | grep "[S]kype") ]] && open -a Skype || echo "Skype is up" 

lợi thế khác là bạn có thể nhận được pid bằng cách thêm một ống để awk '{print $ 1}'.

echo "iTunes pid: $(ps axo pid,command | grep "[i]Tunes.app" | awk '{print $1}')" 
0

tôi đã mở rộng một kịch bản pidof tìm thấy trên mạng để sử dụng biểu thức thông thường (thường là chuỗi con) và là trường hợp nhạy cảm

#!/bin/sh 
ps axc |awk "BEGIN{ n=tolower(\"$1\")}\ 
    tolower(\$5) ~n {print \$1}"; 

chỉ cần tạo một kịch bản có tên là "pidof" với nội dung này, và đặt nó trong bạn con đường, tức là trong một trong những dirs trong

echo $PATH 

và làm cho nó thực thi (có thể sử dụng sudo)

chmod 755 /usr/local/bin/pidof 

và sử dụng nó như thế này, tất nhiên

kill -9 `pidof pyth` 
22

Một giải pháp ngắn:

if pgrep $PROCESS_NAME; then 
    echo 'Running'; 
fi 

Giải thích:

pgrep thoát với 0 nếu có một quá trình phù hợp với $PROCESS_NAME chạy, nếu không nó tồn tại với 1.
if kiểm tra mã thoát của pgrep và, theo như mã thoát, 0 là thành công.

+3

Mặc dù vậy, bạn có thể muốn sử dụng '-x', bởi vì mặc định nó khớp với trên nền. '-x' thay đổi hành vi này sao cho nó yêu cầu đối sánh chính xác của tên quy trình. – Auke

+0

@Hypermattt Nó không phải là câu trả lời được chấp nhận bởi vì anh ấy đã viết nó 4 năm sau khi tôi đặt câu hỏi. Giải pháp mát mẻ, mặc dù. Chắc chắn tôi đã bỏ phiếu. –

+0

Không hoạt động không may nếu bạn đang chạy một thứ gì đó trong trình bao bọc (ví dụ: python). Giải pháp của Jed Smith có thể hoạt động tốt hơn – Evils

0

Có lẽ đã quá muộn cho OP nhưng điều này có thể giúp những người khác tìm thấy chuỗi này.

Việc sửa đổi sau đây của chủ đề amrox trên hoạt động tốt cho khởi động lại ứng dụng trên OS X của tôi:

killall -d TextEdit &> /dev/null && killall TextEdit &> /dev/null; open -a TextEdit 

tôi sử dụng AppleScript sau để cập nhật và khởi động lại daemon:

tell application "System Events" to set pwd to POSIX path of container of (path to me) 
do shell script "launchctl unload -w /Library/LaunchDaemons/time-test.plist; cp -f " & quoted form of pwd & "/time-test.plist /Library/LaunchDaemons; launchctl load -w /Library/LaunchDaemons/time-test.plist" with administrator privileges 

Nó giả định tệp plist gốc hoặc được cập nhật nằm trong cùng thư mục với AppleScript.

3

Bạn có thể sử dụng killall hoặc kill, tùy thuộc vào việc bạn đang cố gắng tìm tác vụ theo PID hay theo tên.

By Name:

if ! killall -s -0 $PROCESS_NAME >/dev/null 2>&1; then 
    # Restart failed app, or do whatever you need to prepare for starting the app. 
else 
    at -f $0 +30seconds # If you don't have this on cron, you can use /usr/bin/at 
fi 

By PID:

if ! kill -0 $PID 2>/dev/null; then 
    # Restart app, do the needful. 
else 
    at -f $0 +30seconds 
fi 

Nếu bạn nhìn vào OSX Manual bạn sẽ thấy một tập hợp khác nhau của lệnh quản lý quy trình; vì nó không phải là hạt nhân Linux, nó có ý nghĩa rằng họ sẽ quản lý các quy trình khác nhau.

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/killall.1.html

Một đầu ra mẫu từ thiết bị đầu cuối của tôi (nổi bật ra người dùng và tên máy, tất nhiên):

[email protected]:~$ kill -0 782 # This was my old, stale SSH Agent. 
bash: kill: (782) - No such process 
[email protected]:~$ echo $? 
1 

[email protected]:~$ kill -0 813 # This is my new SSH agent, I only just created. 
[email protected]:~$ echo $? 
0 

Mã trở về từ một kill -0 sẽ luôn dẫn đến một cách an toàn để kiểm tra xem quá trình có đang chạy hay không, vì -0 sẽ không gửi tín hiệu nào sẽ được ứng dụng xử lý. Nó sẽ không giết chết ứng dụng, và "giết" chỉ được gọi là "giết" vì nó thường được sử dụng để ngăn chặn một ứng dụng.

Khi bạn nhìn vào các giao diện mà nó sử dụng trong nguồn, bạn sẽ thấy rằng nó thực sự tương tác với bảng tiến trình trực tiếp (và không grepping đầu ra có khả năng được tải từ ps), và chỉ gửi tín hiệu đến ứng dụng. Một số tín hiệu cho biết ứng dụng sẽ tắt hoặc dừng, trong khi các tín hiệu khác yêu cầu khởi động lại dịch vụ hoặc đọc lại cấu hình hoặc mở lại các mô tả tệp để ghi nhật ký các tệp đã được xoay gần đây. Có rất nhiều điều mà "giết" và "killall" có thể làm điều đó không chấm dứt các ứng dụng, và nó được sử dụng thường xuyên để chỉ cần gửi một tín hiệu đến ứng dụng.

Các vấn đề liên quan