Làm thế nào để tôi chờ đợi một chương trình bắt đầu trong một vỏ khác


20

Tôi có một chương trình thực hiện một khối lượng công việc lớn (mất khoảng 4-5 giờ) được bắt đầu bằng cron khi tất cả dữ liệu mà nó hoạt động có sẵn. Đôi khi, khi tôi chờ nó kết thúc, tôi muốn có một chương trình (tương tác) khác bắt đầu khi nó kết thúc. Cuộc gọi chờ có vẻ hứa hẹn nhưng sẽ chỉ chờ trẻ em.


Phương pháp duy nhất khác tôi có thể nghĩ ra là tạo một tệp từ cronjob, sau đó sử dụng inotifywait trên quy trình đó, khi các tệp bị xóa, quy trình thứ 2 của bạn (chạy inotifywait) có thể bắt đầu.
slm

Tôi nghĩ rằng bạn có thể làm một cái gì đó dọc theo các dòng này bằng cách sử dụng ipcgiao tiếp liên tiến trình. man ipc.
slm

Mặc dù bạn không xem dịch vụ để khởi động lại dịch vụ, God, Monit hoặc một trong những pkg khác được đề cập trong Q & A này cũng sẽ thực hiện công việc đó: unix.stackexchange.com/questions/75785/ trộm
slm

@slm có thể inotify được sử dụng trên bất kỳ hệ thống tập tin nào, ví dụ như chờ trên close_write trên / Proc / _pid_ / fd / 1?
hildred

Không hoàn toàn chắc chắn, nhưng đó có thể là một cách khác để làm điều đó 8-). Có một số Q mà tôi nhớ nơi có một số chức năng hạt nhân mới liên quan đến giám sát quá trình tương tự như inotifywait (đối với các tệp). Tính năng mới này dành cho các sự kiện đang diễn ra, tôi nghĩ nhưng nhiều câu hỏi và trả lời bắt đầu chạy cùng nhau trong tâm trí tôi 8-). Tôi nghĩ rằng A được cung cấp bởi tôi hoặc Gilles.
slm

Câu trả lời:


13

Tôi chắc chắn thích giải pháp EDIT # 3 (xem dưới đây).

nếu nó không có trong vỏ cùng sử dụng một trong khi vòng lặp với điều kiện trên ps -p trở thành sự thật. Đặt một giấc ngủ trong vòng lặp để giảm việc sử dụng bộ xử lý.

while ps -p <pid> >/dev/null 2>&1
do
   sleep 10
done 

hoặc nếu UNIX của bạn đang hỗ trợ / Proc (ví dụ HP-UX vẫn không).

while [[ -d /proc/<pid> ]]
do 
    sleep 10
done

Nếu bạn muốn thời gian chờ

timeout=6  # timeout after 1mn  
while ((timeout > 0)) && ps -p <pid> >/dev/null 2>&1
do
   sleep 10
   ((timeout -= 1))
done 

EDIT # 1

Có một cách khác: không sử dụng cron . Sử dụng lệnh batch để xếp công việc của bạn.

Ví dụ, bạn có thể sắp xếp hàng ngày tất cả các công việc của bạn. Hàng loạt có thể được điều chỉnh để cho phép một số song song để một công việc bị chặn sẽ không dừng tất cả ngăn xếp (Nó phụ thuộc vào hệ điều hành).

EDIT # 2

Tạo một fifo trong thư mục nhà của bạn:

$ mkfifo ~/tata

khi kết thúc công việc của bạn:

echo "it's done" > ~/tata

khi bắt đầu công việc khác (người đang chờ):

cat ~/tata 

Nó không bỏ phiếu đó là IO cũ chặn tốt.

EDIT # 3

Sử dụng tín hiệu:

Khi bắt đầu tập lệnh, người đang (đang) chờ đợi:

echo $$ >>~/WeAreStopped
kill -STOP $$

vào cuối công việc dài của bạn:

if [[ -f ~/WeAreStopped ]] ; then
    xargs kill -CONT < ~/WeAreStopped
    rm ~/WeAreStopped
fi

Bỏ phiếu, yuck! Quyết định đáng yêu: lãng phí thời gian của bộ xử lý hoặc thời gian của tôi để điều chỉnh giấc ngủ. Phải có một câu trả lời tốt hơn.
hildred

:) Bỏ phiếu là tốt cho bạn, bỏ phiếu là không quốc tịch, bỏ phiếu là đáng tin cậy.
Emmanuel

bỏ phiếu là chậm, poling lãng phí thời gian xử lý.
hildred

Với thời gian thực hiện là 0,01 giây, 1440 ps được thực hiện trong 4 giờ sẽ tiêu tốn 14,4 giây. Ít hơn nhiều so với một người lập lịch quản lý các phụ thuộc công việc: D
Emmanuel

Tôi nghĩ rằng đây có thể là lựa chọn tốt nhất: stackoverflow.com/questions/1058047/ , mặc dù nó rất khó.
slm

5

Bạn có thể sửa đổi công việc định kỳ của mình để sử dụng một số cờ.

Thay vì

2  2 * * *           /path/my_binary

Bạn có thể dùng

2  2 * * *           touch /tmp/i_m_running; /path/my_binary; rm /tmp/i_m_running

Và chỉ cần theo dõi tập tin này trong kịch bản hoặc thậm chí bằng tay. Nếu nó tồn tại, thì chương trình của bạn đang chạy; mặt khác hãy thoải mái làm bất cứ điều gì bạn muốn

Mẫu kịch bản:

while [[ -f /tmp/i_m_running ]] ; do
   sleep 10 ;
done
launch_whatever_you_want

Trong trường hợp bạn không muốn sử dụng sleep, bạn có thể sửa đổi tập lệnh và chạy nó qua cron một lần mỗi X phút.

Trong trường hợp đó, tập lệnh mẫu sẽ là:

[[ -f /tmp/i_m_running ]] && { echo "Too early" ; exit ; }
launch_whatever_you_want

Cách này dễ hơn một chút, vì bạn không phải tìm ra PID của quy trình định kỳ của mình.


4

Không có cơ sở cho một quá trình chờ đợi một quá trình khác kết thúc, ngoại trừ cha mẹ chờ đợi một trong các quy trình con của nó kết thúc. Nếu bạn có thể, hãy khởi chạy chương trình thông qua một tập lệnh:

do_large_amount_of_work
start_interactive_program

Nếu bạn không thể làm điều đó, ví dụ trước khi bạn muốn bắt đầu một lượng lớn công việc từ một công việc định kỳ nhưng chương trình tương tác từ ngữ cảnh của phiên của bạn, thì hãy thực hiện điều này

do_large_amount_of_work
notify_completion

Có một số cách để thực hiện notify_completion. Một số môi trường máy tính để bàn cung cấp cơ chế thông báo ( Mở cửa sổ trên màn hình X từ xa (tại sao "Không thể mở màn hình")? Có thể hữu ích). Bạn cũng có thể thực hiện một bằng cách sử dụng thông báo thay đổi tập tin. Trên Linux, cơ sở thông báo thay đổi tập tin được inotify .

do_large_amount_of_work
echo $? >/path/to/finished.stamp

Để phản ứng với việc tạo ra /path/to/finished.stamp:

inotifywait -e close_write -q /path/to/finished.stamp
start_interactive_program

Nếu bạn không thể thay đổi cách do_large_amount_of_workđược gọi, nhưng bạn biết tệp nào sửa đổi lần cuối, bạn có thể sử dụng cùng một cơ chế để phản ứng khi tệp đó bị đóng. Bạn cũng có thể phản ứng với các sự kiện khác như đổi tên tệp (xem inotifywaithướng dẫn để biết danh sách các khả năng).


0

Có tập lệnh được kích hoạt bởi cronjob gọi một tập lệnh shell rỗng để bạn có thể chèn các tác vụ tiếp theo nếu bạn cần chúng.

Nó rất giống với cách tiếp cận của Gilles.

cronjob-task.sh chứa đựng:

# do_large_amount_of_work

./post-execute.sh

nơi post-execute.shthường trống, trừ khi bạn thấy rằng bạn cần kích hoạt một nhiệm vụ tiếp theo.

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.