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àyNếu nó không chạy, hãy làm điều đó.
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 đó.
Câu trả lời:
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
/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 0
sẽ 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.
-x
tham số để pgrep
nó 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 đó.
! pgrep
Bất kỳ giải pháp sử dụng một cái gì đó như ps aux | grep abc
hoặc pgrep abc
là thiếu sót.
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
, grep
và pgrep
để 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.
Điều đó phụ thuộc vào những gì bạn cần kiểm tra cho.
Đâ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.
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.
pgrep
hoặc ps
hoà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ể.
rm
lệ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.
Đâ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
pgrep
có "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-manager
cũng sẽ thất bại
-x
tù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."
Tôi thường có một đoạn pidof -x $(basename $0)
script để kiểm tra xem nó đã chạy chưa.
Riffing trên ý tưởng của @ rommel-cid, bạn có thể sử dụng pidof
vớ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
$
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 | grep
phươ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
Điều đầu tiên tôi nghĩ đến vấn đề của bạn:
ps aux | grep -i abc
sẽ 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.
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.
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
## 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 lxpanel
hoặc pidof lxpanel
vẫ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 ps
vàgrep
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!
#!/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
zombie
quy 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ácSTAT
giá trị cột, trong đầu ra củaps
, 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ọ.