Làm thế nào để xác định xem một tiến trình có chạy hay không và sử dụng nó để tạo một kịch bản shell có điều kiện?


108

Làm cách nào để xác định xem một tiến trình có chạy hay không và sau đó có một tập lệnh bash thực thi một số nội dung dựa trên điều kiện đó?

Ví dụ:

  • nếu tiến trình abcđang chạy, hãy làm điều này

  • Nếu nó không chạy, hãy làm điều đó.


1
Cảm thấy cần lưu ý rằng không có giải pháp nào dưới đây có tính đến trạng thái của quy trình. Một nhận xét về một trong những câu hỏi của tôi đã đưa tôi đến đây, nhưng một câu trả lời về nó đã đưa tôi vào trạng thái khác nhau của một chương trình, như zombiequy trình '(Không phải là những gì tôi sẽ mô tả như là một quy trình "đang chạy"). Một danh sách đầy đủ về những gì các STATgiá trị cột, trong đầu ra của ps, chỉ ra ở đây cho những người có khuynh hướng viết một câu trả lời phù hợp với điều này hoặc chỉnh sửa chính họ.
user66001


Cách tốt nhất để kiểm tra quy trình tồn tại: stackoverflow.com/questions/3043978/ từ
Trevor Boyd Smith

Câu trả lời:


166

Một kịch bản bash để làm một cái gì đó như thế sẽ trông giống như thế này:

#!/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

Kịch bản này chỉ là kiểm tra xem chương trình "gedit" có đang chạy hay không.

Hoặc bạn chỉ có thể kiểm tra nếu chương trình không chạy như thế này:

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

@DreadPirateShawn bạn có thể cho tôi biết lý do tại sao sử dụng / dev / null và không chỉ đơn giản là 0 không? Sử dụng số làm cho mã dễ đọc hơn, ít nhất là đối với một người mới (chẳng hạn như tôi). Không chuyển hướng, không có gì
Silviu

2
@Silviu hả? Googling /dev/null: "/ dev / null chuyển hướng đầu ra tiêu chuẩn lệnh sang thiết bị null, đây là một thiết bị đặc biệt loại bỏ thông tin được ghi vào nó" ... bằng cách sử dụng 0sẽ chuyển hướng đầu ra lệnh đến một tệp được gọi 0. Trong trường hợp này, tôi khuyên bạn nên trở nên thoải mái hơn > /dev/null- bạn sẽ thấy nó ở mọi nơi, vì đó là cách tiêu chuẩn / phù hợp để loại bỏ đầu ra.
DreadPirateShawn 10/11/2015

Cảm ơn, tôi đã sử dụng cái này cho một đoạn script nhỏ để kiểm tra xem một chương trình có chạy trước khi nó thực thi không. (mặc dù tôi đã phải gia hạn thêm một chút vì thực thi của Google chrome không có cùng tên với lệnh chạy, tên thực thi chỉ là chrome.)
Cestarian

3
Vui lòng thêm -xtham số để pgrepnó tìm kiếm ứng dụng chính xác nếu không nó sẽ nhận được sai nếu tìm thấy cùng một chuỗi bên trong tên của ứng dụng khác. Tôi chỉ mất 1 giờ để tìm ra điều đó.
Thanos Apostolou

1
Để kiểm tra xem chương trình có chạy không, hãy sử dụng! pgrep
Mohammed Noureldin

36

Bất kỳ giải pháp sử dụng một cái gì đó như ps aux | grep abchoặc pgrep abclà thiếu sót.

Tại sao?

Bởi vì bạn không kiểm tra xem một quy trình cụ thể có đang chạy hay không, nên bạn đang kiểm tra xem có bất kỳ quy trình nào đang chạy phù hợp hay không abc. Bất kỳ người dùng nào cũng có thể dễ dàng tạo và chạy một tệp thực thi có tên abc(hoặc có chứa abcở đâu đó trong tên hoặc đối số của nó), gây ra kết quả dương tính giả cho thử nghiệm của bạn. Có những lựa chọn khác nhau mà bạn có thể áp dụng cho ps, greppgrepđể thu hẹp tìm kiếm, nhưng bạn vẫn sẽ không nhận được một thử nghiệm đáng tin cậy.

Vì vậy, làm thế nào để tôi kiểm tra đáng tin cậy cho một quy trình chạy nhất định?

Điều đó phụ thuộc vào những gì bạn cần kiểm tra cho.

Tôi muốn đảm bảo rằng dịch vụ abc đang chạy, và nếu không, hãy khởi động nó

Đây là những gì init và upstart dành cho. Họ sẽ bắt đầu dịch vụ và đảm bảo pid của nó được lưu trữ trong pidfile. Hãy thử khởi động lại dịch vụ (thông qua init hoặc khởi động) và nó sẽ kiểm tra pidfile và khởi động nó nếu nó không ở đó hoặc hủy bỏ nếu nó đang chạy. Điều này vẫn không đáng tin cậy 100%, nhưng nó gần như bạn nhận được.

Xem Làm thế nào tôi có thể kiểm tra xem máy chủ trò chơi của tôi có còn chạy không ... để biết các giải pháp khác.

abc là kịch bản của tôi Tôi cần đảm bảo chỉ có một phiên bản tập lệnh của tôi đang chạy.

Trong trường hợp này, sử dụng lockfile hoặc lockdir. Ví dụ

#!/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 ...

Xem Bash FAQ 45 để biết các cách khóa khác.


3
Trong khi điều này là đúng về mặt kỹ thuật, cá nhân tôi đã gặp phải một vấn đề như vậy trong cuộc sống thực. Hầu hết các chương trình không thay đổi tên của họ theo cách phá vỡ các tập lệnh. Do đó, đối với các tập lệnh đơn giản, một cái gì đó giống pgrephoặc pshoàn toàn phù hợp và cách tiếp cận của bạn có vẻ như quá mức cần thiết. Tuy nhiên, nếu bạn đang viết một bản thảo để phân phối công khai, bạn nên viết nó theo cách an toàn nhất có thể.
Scott Severance

2
@ScottSeverance Chương trình thay đổi tên không phải là vấn đề; điều đó đòi hỏi phải can thiệp bất kể Đó là những người dùng khác đang chạy cùng một chương trình hoặc các chương trình khác có tên tương tự sẽ đột nhiên khiến tập lệnh nhận được thông báo sai và do đó làm sai. Tôi chỉ thích "công việc" hơn là "chủ yếu hoạt động".
geirha

2
Tôi đã bỏ lỡ. Nhưng nhiều người trong chúng ta chạy các hệ thống người dùng đơn. Và trong một tình huống nhiều người dùng, thật dễ dàng để grep cho tên người dùng.
Scott Severance

1
Điều gì xảy ra nếu tập lệnh của bạn bị lỗi trong thời gian chạy và chết trước khi mở khóa tệp?
jp093121

2
@ jp093121 Bẫy EXIT được kích hoạt khi thoát tập lệnh. Cho dù nó thoát vì nó đến cuối tập lệnh, lệnh thoát hoặc nhận tín hiệu (có thể được xử lý), rmlệnh sẽ được chạy. Vì vậy, miễn là nó kết thúc sau khi đặt bẫy, khóa sẽ không còn nữa.
geirha

18

Đây là những gì tôi sử dụng:

#!/bin/bash

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

Nói một cách dễ hiểu: nếu 'pgrep' trả về 0, quá trình đang chạy, nếu không thì không.


Đọc liên quan:

Bash Scripting :: So sánh chuỗi

Hướng dẫn sử dụng Ubuntu pgrep


thanx! tôi cũng đã thử nó và nó cũng hoạt động hoàn hảo :)
Nirmik

pgrepcó "tính năng" giới hạn 15 ký tự giống như đã đề cập trước đây, do đó, ví dụ pgrep gnome-power-managercũng sẽ thất bại
Thorsen

1
Đảm bảo bạn sử dụng -xtùy chọn của pgrep : "Chỉ khớp các quy trình có tên (hoặc dòng lệnh nếu -f được chỉ định) khớp chính xác với mẫu."
Alastair Irvine

5

Tôi thường có một đoạn pidof -x $(basename $0)script để kiểm tra xem nó đã chạy chưa.


2

Riffing trên ý tưởng của @ rommel-cid, bạn có thể sử dụng pidofvới || (||) để chạy lệnh nếu quy trình không tồn tại và && để chạy một cái gì đó nếu quy trình đó tồn tại, do đó tạo ra một điều kiện if / then / other nhanh chóng. Ví dụ: đây là một quy trình đang chạy (trình duyệt chrome của tôi, có tên quy trình là "chrome") và một thử nghiệm cho một quy trình không tồn tại. Tôi đã loại bỏ đầu ra tiêu chuẩn bằng cách sử dụng 1> / dev / null để nó không in:

$ (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
$

1

Không có giải pháp "đơn giản" nào phù hợp với tôi vì nhị phân tôi cần kiểm tra không được cài đặt trên toàn hệ thống, vì vậy tôi phải kiểm tra bằng đường dẫn, do đó yêu cầu sử dụng ps -ef | grepphương pháp tiếp cận:

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

0

Điều đầu tiên tôi nghĩ đến vấn đề của bạn:
ps aux | grep -i abcsẽ hiển thị chi tiết về quy trình nếu nó đang chạy. Bạn có thể khớp số lượng dòng hoặc thời gian mà nó chạy và so sánh với số không hoặc bất kỳ thao tác nào khác. Khi bạn chạy lệnh trên, nó sẽ hiển thị cho bạn ít nhất một dòng đầu ra tức là chi tiết về quá trình được tạo bởi lệnh thi grep .. Vì vậy, hãy quan tâm đến điều đó.
Điều đó nên làm như một hack đơn giản. Đặt nó trong tập lệnh bash và xem nếu nó hữu ích.


0

Sử dụng start-stop-daemon:

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

Nó hoạt động như người dùng bình thường.


0

Tôi thấy rằng câu trả lời được chấp nhận được đăng bởi @John Vrbanac không phù hợp với tôi và câu trả lời được đăng bởi @geirha không trả lời câu hỏi ban đầu.

Giải pháp của John Vrbanac không hoạt động để kiểm tra xem một quy trình PHP có chạy hay không đối với tôi, tôi đang chạy CentOS 7.

Câu trả lời của @ geirha chỉ đảm bảo một phiên bản chưa chạy trước khi bắt đầu một phiên bản khác. Đây không phải là câu hỏi ban đầu, câu hỏi ban đầu là để kiểm tra xem một quá trình có đang chạy hay không.

Đây là những gì làm việc cho tôi:

Giả sử quy trình của tôi có chuỗi "Jane" trong tên quy trình của nó. Điều này sẽ tìm thấy nếu nó chạy hay không. Điều này hoạt động cho các kịch bản BASH và PHP.

ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "It's running"
else
    echo "It's not running"
fi

1
À, đây cũng là một trang web Hỏi & Đáp về Ubuntu, không có gì đáng ngạc nhiên khi một số câu trả lời ở đây không hoạt động trên CentOS 7 vì Linux không có chủ đề ở đây. Các phiên bản khác của Linux được hỗ trợ tại unix.stackexchange.com
Elder Geek

mặc dù tác giả của câu trả lời sử dụng CentOS, nhưng câu trả lời này vẫn hợp lệ đối với 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 &)

Lưu ý : pgrep -x lxpanelhoặc pidof lxpanelvẫn báo cáo lxpanelđang chạy ngay cả khi không còn tồn tại (zombie); Vì vậy, để có được quá trình sống và chạy, chúng ta cần sử dụng psgrep


-1

Kể từ ngày 23 tháng 9 năm 2016, pgrep dường như yêu cầu tùy chọn "-x" để kịch bản của muru hoạt động.

#!/bin/bash

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

Tôi đã thử và kiểm tra đoạn script trên trên máy Ubuntu 16.04.1. Thưởng thức!


-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

1
Chào mừng bạn đến hỏi Ubuntu! Tôi khuyên bạn nên chỉnh sửa câu trả lời này để mở rộng nó với các chi tiết cụ thể về những gì nó làm. (Xem thêm Làm thế nào để viết một câu trả lời tốt? Cho lời khuyên chung về những gì các loại câu trả lời được coi là có giá trị nhất trên AskUbuntu.)
David Foerster

-3

isProcessRasty () {if [$ (pidof $ 1)> / dev / null]; sau đó retval = 'true'; khác retval = 'false'; fi; echo $ retval; }

isProcessRucky geany

thật

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.