Có cách nào để một tập lệnh bash biết nó đang chạy ở nền trước hay nền không, và vì vậy nó có thể hành xử hơi khác nhau trong mỗi trường hợp?
Có cách nào để một tập lệnh bash biết nó đang chạy ở nền trước hay nền không, và vì vậy nó có thể hành xử hơi khác nhau trong mỗi trường hợp?
Câu trả lời:
Trích dẫn man ps
:
Here are the different values that the s, stat and state output
specifiers (header "STAT" or "S") will display to describe the state of
a process.
...
+ is in the foreground process group
Vì vậy, bạn có thể thực hiện một kiểm tra đơn giản:
case $(ps -o stat= -p $$) in
*+*) echo "Running in foreground" ;;
*) echo "Running in background" ;;
esac
Nhìn vào tệp /etc/bash.bashrc ".
Dòng có "$ PS1". Sau đó thực hiện "man bash" và tìm mã thông báo PS1.
[ -z "$PS1" ] && return
thoát khỏi một kịch bản không tương tác.
Tất cả các giải pháp trước đó liên quan đến các quá trình sinh sản, v.v. Rất, rất xấu, vì .bashrc
được gọi mỗi khi bash shell khởi chạy, do đó các giải pháp đó kết thúc khởi động 1000 quy trình.
Nhiều người dọn dẹp hơn đang tự hỏi bash: bash có một biến được xác định trước $-
có "i" nếu nó chạy trong một vỏ tương tác. Ví dụ: đặt cái này vào .bashrc của bạn sạch hơn và rẻ hơn nhiều và quan trọng nhất là sẽ luôn hoạt động!
case "$-" in
*i*) # interactive shell
;;
esac
Mặc dù bạn có thể nghĩ rằng việc kiểm tra xem shell có chạy trong chế độ tương tác hay không sẽ cho kết quả tương tự, nhưng thực tế, điều này không xảy ra. Khái niệm này trông giống nhau nhưng thực sự khác nhau. Bạn có thể chạy một kịch bản tương tác trong đầu vào cho ăn nền nhờ mong đợi . Ngoài ra, bạn có thể khởi chạy tập lệnh của mình bằng bash với -l
đối số. Do đó, chúng tôi không thể dựa vào tính tương tác của bash để kiểm tra xem tập lệnh của chúng tôi có chạy ở chế độ nền hay ở nền trước hay không.
Câu trả lời từ devnull là do đó chính xác . Để xác định xem quy trình có chạy ở nền trước hay không, tiện ích ps kiểm tra xem nhóm quy trình (pgrp) có giống với id nhóm quy trình được liên kết với thiết bị đầu cuối kiểm soát của phiên (tpgid) không và thêm +
dấu hiệu vào đầu ra theo quy trình tiểu bang.
Biết rằng, chúng tôi chắc chắn có thể có một phiên bản thử nghiệm bash thuần túy:
#!/usr/bin/env bash
IFS=$' '
retval=($(</proc/$$/stat))
IFS=$' \t\n'
if [[ "${retval[3]}" == "${retval[7]}" ]]; then
echo "Background" > ./result.txt
else
echo "Foreground" > ./result.txt
fi
exit
Trong đoạn mã trên, chúng tôi xuất kết quả trong tệp văn bản vì stdout
không được kết nối khi một tiến trình được chạy trong nền.
Vui lòng lưu ý các yếu tố thứ 4 và thứ 8 của bảng tương ứng với pgrp
và tpgid
( xem phần / Proc / [pid] / stat của trang man - man 5 proc
).