POSIX tương đương với thời gian chờ GNU?


14

Lệnh GNU coreutils timeoutcực kỳ tiện lợi cho một số tình huống kịch bản nhất định, cho phép sử dụng đầu ra của lệnh nếu chạy nhanh và bỏ qua nếu mất quá nhiều thời gian.

Làm cách nào tôi có thể tính gần đúng hành vi cơ bản của timeoutviệc chỉ sử dụng các tiện ích được chỉ định POSIX?


(Tôi nghĩ nó có thể liên quan đến một sự kết hợp của wait, sleep, killvà ai biết được điều gì khác, nhưng có lẽ tôi là thiếu một cách tiếp cận dễ dàng hơn.)


3
Xem Thời gian chờ trong tập lệnh shell , nhưng tôi không coi đây là một bản sao vì tôi đã yêu cầu tính di động đối với các hệ thống tiền POSIX và tôi có yêu cầu duy trì stdin và stdout mà một số giải pháp liên quan đến quy trình nền loại trừ.
Gilles 'SO- ngừng trở nên xấu xa'

command & pid=$! ; sleep 5 && kill $pid
Pandya

1
@Pandya không giới thiệu một điều kiện chủng tộc nhỏ, trong đó nếu commandkết thúc nhanh chóng, có khả năng nhỏ pidsẽ bị tái sử dụng bởi một quy trình khác bắt đầu trước khi killlệnh chạy? Tôi sẽ không muốn điều đó trong mã sản xuất ....
Wildcard

Bạn có thể giải thích thêm về vấn đề tiềm ẩn mà bạn đang cố gắng giải quyết không? Tại sao không chỉ biên dịch timeoutchương trình và sử dụng nó?
James Youngman

2
@JamesYoungman, tôi đoán bạn không rành lắm về việc viết kịch bản cho tính di động . Yêu cầu một cách tuân thủ POSIX (hoặc được chỉ định bởi POSIX) ngụ ý rằng nó dự định là có thể mang theo được. Biên dịch mã nguồn thành một nhị phân là một cách dứt khoát không cầm tay, và, tùy thuộc vào chính sách bảo mật công ty, bạn có thể không có một trình biên dịch được cài đặt tại tất cả trên một máy chủ sản xuất.
tự đại diện

Câu trả lời:


2

Cách tiếp cận của tôi sẽ là cái này:

  • Thực thi lệnh làm tiến trình nền 1

  • Thực hiện "bộ định thời watchdog" làm tiến trình nền 2

  • Thiết lập trình xử lý để bẫy tín hiệu kết thúc trong vỏ cha

  • Đợi cả hai quá trình hoàn thành. Quá trình kết thúc trước, gửi tín hiệu kết thúc cho cha mẹ.

  • Trình xử lý bẫy của cha mẹ giết chết cả hai quá trình nền thông qua kiểm soát công việc (một trong số chúng đã bị chấm dứt theo định nghĩa, nhưng việc giết đó sẽ là vô hại vì chúng ta không sử dụng PID, xem bên dưới)

Tôi đã cố gắng phá vỡ điều kiện cuộc đua có thể được giải quyết trong các bình luận bằng cách sử dụng ID kiểm soát công việc của shell (sẽ không rõ ràng trong trường hợp shell này) để xác định các quy trình nền để giết, thay vì các hệ thống PID.

#!/bin/sh

TIMEOUT=$1
COMMAND='sleep 5'

function cleanup {
    echo "SIGTERM trap"
    kill %1 %2
}

trap cleanup SIGTERM

($COMMAND; echo "Command completed"; kill $$) &
(sleep $TIMEOUT; echo "Timeout expired"; kill $$) &

wait
echo "End of execution"

Kết quả cho TIMEOUT=10(lệnh chấm dứt trước watchdog):

$ ./timeout.sh 10
Command completed
SIGTERM trap
End of execution

Kết quả cho TIMEOUT=1(watchdog chấm dứt trước khi ra lệnh):

$ ./timeout.sh 1
Timeout expired
SIGTERM trap
End of execution

Kết quả cho TIMEOUT=5(watchdog và lệnh chấm dứt "gần như" đồng thời):

./tst.sh 5
Timeout expired
Command completed
SIGTERM trap
End of execution

Đây không phải là tuân thủ POSIX vì (a) định nghĩa chức năng nên cleanup() { ...; }và (b) kiểm soát công việc là một tính năng bash không được chỉ định bởi POSIX (mặc dù ksh và những người khác cũng có). Kịch bản tốt, mặc dù!
tự đại diện

Bạn cũng có thể làm tốt hơn với timeout="$1"; shift(exec "$@"; echo "Command completed"; kill $$) thay vì viết lại danh sách đối số.
tự đại diện
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.