Làm thế nào một tập lệnh bash có thể phát hiện nếu nó đang chạy trong nền?


28

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?


Lưu ý rằng một quy trình có thể chuyển từ tiền cảnh sang nền và ngược lại vì kiểm soát công việc.
Barmar

1
Bạn cũng có thể muốn biết liệu tập lệnh có chạy từ trình bao tương tác hay không
GnP

Câu trả lời:


30

Trích dẫn man ps:

QUY TRÌNH NHÀ NƯỚC

   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

Chắc chắn bất cứ thứ gì được gọi trong $ (...) đều tự chạy trong nền ....? Tôi đoán rằng nhóm quy trình là điều quan trọng mặc dù, không thể phủ nhận rằng nó hoạt động.
Ed Randall

2

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.


1

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

TẠI SAO BẠN LẠI HÉT? Đó là vẻ bề ngoài rất, rất xấu xí ...
Pierre.Vriens

Giải pháp đơn giản, đúng đắn.
Ed Randall

0

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ì stdoutkhô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 pgrptpgid( xem phần / Proc / [pid] / stat của trang man - man 5 proc).

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.