2011-01-22 32 views
12

thể trùng lặp:
Quick-and-dirty way to ensure only one instance of a shell script is running at a timeShell script: Đảm bảo rằng kịch bản không được thực hiện nếu đang chạy

tôi đã thiết lập một cronjob để sao lưu các thư mục của tôi đúng mà tôi khá tự hào về. Tuy nhiên tôi đã phát hiện ra, bằng cách xem kết quả từ các bản sao lưu, tập lệnh sao lưu của tôi đã được Crontab gọi nhiều lần, dẫn đến nhiều bản sao lưu đang chạy cùng một lúc.

Có cách nào tôi có thể đảm bảo rằng một tập lệnh shell nhất định không chạy nếu cùng một tập lệnh đã thực thi không?

Cảm ơn

+0

Câu hỏi tương tự: http://stackoverflow.com/questions/ 1440967/how-do-i-make-sure-my-bash-script-isnt-already-running – mizo

+0

Vui lòng xem [Quản lý quy trình] (http://mywiki.wooledge.org/ProcessManagement). –

Trả lời

33

Một giải pháp không có điều kiện chủng tộc hoặc các vấn đề về lối ra sớm là sử dụng tệp khóa. Tiện ích flock xử lý này rất tốt và có thể được sử dụng như thế này:

flock -n /var/run/your.lockfile -c /your/script 

Nó sẽ trở lại ngay lập tức với một tình trạng phi 0 nếu kịch bản vẫn đang chạy.

0

Bạn có thể sử dụng tệp tmp.
Đặt tên nó là tmpCronBkp.a, tmpCronBkp.b, tmpCronBkp.c ... v.v. Đã xếp lại tập lệnh sao lưu yout.

Tạo nó trên kịch bản bắt đầu và xóa nó ở cuối ...

Trong một thời gian, kiểm tra nếu tập tin tồn tại hay không và những gì tập tin tồn tại.

Bạn đã thử cách này chưa?

+0

Tôi không chắc liệu mình có làm cho mình hoàn toàn rõ ràng hay không, nhưng tôi muốn đảm bảo rằng kịch bản lệnh shell của tôi không được thực hiện lại, nếu nó đã được CRON gọi và hoạt động – Industrial

+0

Hãy để tệp này giữ PID của quá trình bắt đầu. Vì vậy, bạn sẽ có thể tìm ra là nó chạy ở tất cả. – akond

+0

có, bạn có thể kiểm tra tệp tmp và thoát khỏi scrit nếu tệp tồn tại! – elp

7

Cách thông thường và đơn giản để làm điều này là đặt một cái gì đó như:

if [[ -f /tmp/myscript.running ]] ; then 
    exit 
fi 
touch /tmp/myscript.running 

ở phía trên cùng của bạn kịch bản và

rm -f /tmp/myscript.running 

ở cuối, và trong trap chức năng trong trường hợp nó không đạt được kết thúc.

Điều này vẫn còn một số vấn đề tiềm ẩn (chẳng hạn như điều kiện chủng tộc ở trên cùng) nhưng sẽ làm cho đại đa số trường hợp.

+0

điều này sẽ ngăn chặn tập lệnh chạy nếu nó được chạy trước đó. – unbeli

+0

@unbeli: không có nó sẽ không, bởi vì bạn loại bỏ các tập tin sentinel khi thoát. – paxdiablo

+9

Có một điều kiện chủng tộc vì TOCTOU (thời gian kiểm tra, thời gian sử dụng) giữa 'tệp không tồn tại' và 'tạo tệp'. Cơ chế nguyên tử là 'mkdir /tmp/myscript.running 2>/dev/null'. Nếu thư mục tồn tại, 'mkdir' sẽ thất bại, và hạt nhân bảo đảm rằng chỉ có một lệnh chạy đồng thời' mkdir' (các cuộc gọi hệ thống) thành công. –

5

Cách tốt nhất mà không có một tập tin khóa:

ps | grep $0 | grep -v grep > /var/tmp/$0.pid 
pids=$(cat /var/tmp/$0.pid | cut -d ' ' -f 1) 
for pid in $pids 
do 
    if [ $pid -ne $$ ]; then 
     logprint " $0 is already running. Exiting" 
     exit 7 
    fi 
done 
rm -f /var/tmp/$0.pid 

này làm nó mà không có một tập tin khóa, đó là mát mẻ. ps vào tệp tạm thời, loại bỏ trường đầu tiên (pid #) và tìm kiếm chính mình. Nếu chúng ta tìm thấy một cái khác, thì ai đó đã chạy. Các grep $ 0 là để rút ngắn danh sách để chỉ những trường hợp của chương trình này, và grep -v grep được thoát khỏi dòng đó là grep chính nó :)

+1

Đơn giản hơn để sử dụng pgrep: 'pids = $ (pgrep $ 0); cho pid bằng $ pids' – Jeremy

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