Cách Bash để kiểm tra nếu một quá trình đã chạy trong nền (và bỏ qua thực hiện lại dựa trên đó)?


11

Tôi có thể tạo một dòng lệnh bash chỉ chạy một lệnh nhất định nếu quá trình chưa chạy (trong nền) không?

Làm cách nào để kiểm tra *, nếu một lệnh đã chạy?

(vì vậy tôi có thể thêm lệnh tiếp theo &&ở giữa chúng để lệnh tiếp theo chỉ thực thi nếu lệnh đầu tiên là đúng).

*: kiểm tra, xác định, khám phá, tìm hiểu


3
ps -ef | grep -v grep | grep "process_name" || run_command_here
Rahul Patil

1
@RahulPatil bạn chỉ có thể sử dụng pgrep "process_name"thay vìps | grep | grep
vội vàng

hmm, tôi quên điều đó ..: D
Rahul Patil

1
Tại sao bạn không sử dụng tệp "khóa" và khi bạn khởi chạy lần thứ hai, nó sẽ chỉ khởi chạy khi tệp khóa biến mất.
BitsOfNix

cách tốt nhất để kiểm tra xem có tồn tại một quy trình hay không: stackoverflow.com/questions/3043978/ cấp
Trevor Boyd Smith

Câu trả lời:



3

Thỉnh thoảng tôi đã sử dụng kỹ thuật này:

$ pgrep <process name> || <process name>

Trước pgrepđó nó thường được thực hiện theo cách này:

$ ps -eaf | grep -q <[p]rocess name> || <process name>

thí dụ

Kết quả là [p]làm cho nó grepsẽ không tìm thấy kết quả.

$ ps -eaf | grep -q [s]leep || sleep 10

2

Điều này có thể khó khăn, bởi vì bạn có thể có các trường hợp riêng biệt của cùng một quá trình sống độc lập. Ví dụ: máy chủ lắng nghe trên các cổng khác nhau hoặc dịch vụ chạy như những người dùng khác nhau. Để phân biệt giữa các trường hợp này, bạn cần gán cho mỗi thẻ một thẻ duy nhất. Thẻ thường là một tệp, nhưng nó có thể là một ổ cắm cục bộ trong không gian tên trừu tượng, cổng TCP, v.v. - bất kỳ định danh duy nhất nào cũng được. Khi thẻ là một tệp, nó có thể là một tệp thông thường chứa ID tiến trình (pidfile) hoặc ống hoặc ổ cắm có tên mà tệp đang nghe, v.v. Lý tưởng nhất, thẻ là điểm cuối giao tiếp cho phép khách hàng kết nối để quá trình đó.

Mỗi loại thẻ khác nhau này dẫn đến một cách khác nhau để kiểm tra xem phiên bản bạn đang tìm kiếm có hoạt động hay không. Ví dụ, với một ổ cắm tệp cục bộ, hãy thử kết nối với nó và bắt đầu quá trình nếu không có quá trình lắng nghe trên ổ cắm đó. Nếu thẻ là pidfile, hãy kiểm tra xem có một quy trình với ID quy trình đó không, nhưng hãy cẩn thận rằng đây là quy trình dễ vỡ, vì nếu quy trình đã chết, có thể có một quy trình không liên quan đã sử dụng lại ID của nó. Xin lưu ý rằng nếu hai khách hàng cố gắng đạt được quy trình trong một khung thời gian ngắn, cả hai có thể thấy rằng quy trình không tồn tại và cả hai đều cố gắng bắt đầu quy trình; bảo vệ đúng cách khỏi điều kiện cuộc đua này có thể là khó khăn.

Việc quản lý các trường hợp sẽ dễ dàng hơn khi tất cả chúng được bắt đầu bởi cùng một quy trình giám sát và quy trình giám sát đó phát hiện khi các cá thể chết và phản ứng tương ứng. Nhiều chương trình giám sát dịch vụ có thể làm điều này.

Nếu chương trình không phản hồi trên điểm cuối giao tiếp đã biết và nó không được quản lý bởi chương trình giám sát, thẻ của người nghèo là pidfile: một tệp chứa ID tiến trình. Khi bạn bắt đầu quá trình, hãy viết pid vào một tệp có tên được sắp xếp trước. Khi bạn cần quá trình tồn tại, hãy đọc pidfile và xem liệu có một quy trình với pid đó không. Khi bạn giết quá trình, xóa pidfile. Vấn đề nổi bật nhất với pidfile không được giám sát là nếu quá trình này chết, pid của nó có thể được sử dụng lại bởi một số quy trình không liên quan. Ít nhất bạn nên kiểm tra tên quy trình hoặc quy trình thực thi để đảm bảo rằng bạn đang nói đúng quy trình. Nhiều biến thể unix có lệnh pgrep :pgrep SOMENAME liệt kê các quy trình có tên chứa SOMENAME dưới dạng một chuỗi con, với các tùy chọn bổ sung để giới hạn cho một người dùng cụ thể, để yêu cầu một kết hợp chính xác, để thay đổi một số khái niệm có thể có của tên quy trình có thể sử dụng, v.v.


1

Bạn có thể sử dụng phương pháp này:

if [[ -z $(ps -C appname -opid=) ]]; then
    appname && secondapp
fi

1

Sự lựa chọn khác:

  • pgrep -xq processname
    • Chỉ khớp với 15 ký tự đầu tiên trong GNU / Linux
    • Không bao gồm tổ tiên trên OS X
  • ps -eo comm= | sed 's|.*/||' | grep -xq processname
    • Chỉ khớp với 15 ký tự đầu tiên trong GNU / Linux
    • sed 's|.*/||' xóa các phần dirname trên OS X

Trong GNU / Linux ps -o commcắt ngắn tên lệnh thành 15 ký tự pgrepps -Cchỉ khớp với 15 ký tự đầu tiên.

ps -C (tên lệnh khớp) không được hỗ trợ trên OS X.

Trong OS X ps -o commin các đường dẫn tuyệt đối của lệnh và ps -co commchỉ in tên lệnh. Trong GNU ps -o commchỉ in tên lệnh và -ccó nghĩa khác.

Pgrep của OS X không bao gồm các quy trình tổ tiên (như bash, Terminal hoặc launchd) mà không có -a. Pgrep của GNU bao gồm chúng theo mặc định và nó không hỗ trợ -a.

grep -xpgrep -xkhông ngụ ý -F, vì vậy hãy sử dụng -Fxnếu tên tiến trình có thể chứa các ký tự regex.


-C cũng không có sẵn trong cygwin của tôi :)
n611x007

1

Tôi xin lỗi nhưng tất cả các giải pháp này không hỗ trợ contab vì cùng một dòng lệnh sẽ xuất hiện hai lần trong kết quả 'ps'.

Vì vậy, đây là của tôi:

## Test pour voir si le même script tourne déjà
## Un fichier .pid est utilisé pour stocké le numéro de process
## Si le pid est en train de tourner alors on sort.
lock_file=$0".pid"
[ -r $lock_file ] && read pid <$lock_file
if [ "$pid" -gt 1 ] && [ `ps --no-headers -p "$pid" | wc -l` -gt 0 ] ; then
    echo "WARNING : le process $pid tourne deja : $0"
    ps -edf | grep `basename $0` | grep -v grep
    echo "WARNING : Arrêt de cette instance ($$)."
    exit 7
fi
echo $$ >$lock_file

Bạn xin lỗi về điều gì? Contab là gì? Bạn có nghĩa là kiểm tra từ trong một croncông việc?
Anthon

0

Với Bash

#!/usr/bin/env bash

[[ $# -eq 0 ]] && { echo -e "Usage:\t\t $0 <Process_name>  <Command here>"; exit 1;  }

ifnotrun(){
        local p=$1
        if ! ps -C "$1" -opid=
        then
                cmd=($@)
                echo ${cmd[@]:1}
        else
                echo "Process \"$p\" Already Running.."
                exit 1
        fi

}

ifnotrun $*

Lưu ý: - loại bỏ echonếu đầu ra trông Ok.


0

Tôi sẽ giải thích trường hợp bạn chạy lệnh trong beckgreoud. "$!" lưu PID của bộ xử lý nền cuối cùng. Vì vậy, bạn có thể sử dụng nó để tìm nó trong các bảng xử lý theo các câu trả lời ở trên:

sleep 4 &
ps -ef | grep -w  $!  ...

Lệnh dựng sẵn "công việc" - hãy thử điều này:

sleep 4&
J=`jobs`
while [ "$J" ]; do
        sleep 1
        jobs # This line flush the jobs' bufer.
        J=`jobs`
done

Về tùy chọn "&&"

Thay vì && sử dụng lệnh chờ. Trong ví dụ sau myproc2 sẽ không chạy cho đến khi myproc1 kết thúc:

myproc1 &
wait
myproc2

0

Nhận trạng thái của quá trình của bạn:

ps -lp $(pgrep <YOUR_PROCESS_NAME>) | tail -1 | awk '{print $11}'

Tài liệu tham khảo:

D    uninterruptible sleep (usually IO)
R    running or runnable (on run queue)
S    interruptible sleep (waiting for an event to complete)
T    stopped, either by a job control signal or because it is being traced
W    paging (not valid since the 2.6.xx kernel)
X    dead (should never be seen)
Z    defunct ("zombie") process, terminated but not reaped by its parent

Ví dụ: tôi đã sử dụng nó để chơi hoặc tạm dừng quá trình sox của mình trong phiên tmux:

/usr/local/bin/tmux if-shell -t sox "[ $(ps -lp $(pgrep sox) | tail -1 | awk '{print $11}') == 'T' ]" \
  'send -t sox "fg" Enter' \
  'send -t sox C-z'

-1

Bạn có thể sử dụng nó trong một tập lệnh:

if [ `ps -ef | grep "script.sh" | grep -v grep | wc -l` -gt 1 ] ; then
echo "RUNNING...."
else
echo "NOT RUNNING..."
fi
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.