Dịch vụ biến đổi dữ liệu của ampeand (nền tảng một quá trình)


9

Tôi muốn biết nếu có một cách để đặt dấu và trong một biến và vẫn sử dụng nó để gửi một quá trình đến nền.

Những công việc này:

BCKGRND=yes
if [ "$BCKGRND" = "yes" ]; then
    sleep 5 &
else
    sleep 5
fi

Nhưng sẽ không hay ho gì khi hoàn thành năm dòng đó chỉ với một dòng? Thích như vậy:

BCKGRND='&'
sleep 5 ${BCKGRND}

Nhưng điều đó không hiệu quả. Nếu BCKGRND không được đặt thì nó hoạt động - nhưng khi được đặt, nó được hiểu là chữ '&' và lỗi.


sau khi sử dụng dấu và, echo $!trả về PID
noobninja

Câu trả lời:


9

Không thể sử dụng một biến để làm nền cuộc gọi vì việc mở rộng biến xảy ra sau khi dòng lệnh được phân tích cú pháp cho các toán tử điều khiển (chẳng hạn như &&&).

Tuy nhiên, một tùy chọn khác sẽ là bọc các cuộc gọi trong một chức năng:

mayberunbg() {
  if [ "$BCKGRND" = "yes" ]; then
    "$@" &
  else
    "$@"
  fi
}

... Và sau đó đặt biến khi cần:

$ BCKGRND=yes mayberunbg sleep 3
[1] 14137
$
[1]+  Done                    "$@"
# or
$ BCKGRND=yes
$ mayberunbg sleep 3
[1] 14203
$
[1]+  Done                    "$@"
$ BCKGRND=no mayberunbg sleep 3
# 3 seconds later
$

Gì, không có ed? Dù sao +1, đây là giải pháp sạch nhất.
Stephen Kitt

LOL @StephenKitt; bây giờ các bánh răng đang quay
Jeff Schaller

Tôi thích câu trả lời eval vì tính đơn giản của nó nhưng lệnh thực tế trong thế giới thực mà tôi muốn làm nền quá phức tạp với quá nhiều biến trong đó để có thể thoải mái sử dụng eval. @ jeff-schaller đã đưa ra câu trả lời chỉ cho tôi hướng đi. Tuy nhiên, thay vì một hàm, tôi đặt toàn bộ lệnh vào một biến sau đó sử dụng kiểu câu lệnh if của mình để thực thi lệnh có hoặc không có &.
BrowncoatOkie

11

Bạn có thể lật mọi thứ và variabilise vào trước foregrounding

FOREGROUND=fg
sleep 5 & ${FOREGROUND}

Đặt FOREGROUNDthành truehoặc trống để chạy quá trình trong nền. (Cài đặt FOREGROUNDđể truechạy trong nền được thừa nhận là khó hiểu! Tên biến thích hợp được để lại làm bài tập cho người đọc.)


4
điều đó thật tuyệt nhưng nó sẽ không hoạt động trong trình bao mà không có kiểm soát công việc (tức là bất kỳ tập lệnh nào trừ khi set -mđược sử dụng).
mosvy

9

Bạn có thể sẽ phải sử dụng eval:

eval "sleep 5" "$BCKGRND"

evallàm cho vỏ để đánh giá lại các đối số được đưa ra. &Do đó, một nghĩa đen sẽ được hiểu là &ở cuối một lệnh và không phải là một đối số cho lệnh, đặt lệnh trong nền.


2
Một câu trả lời có evalchứa cảnh báo, rằng điều này cần được xử lý cẩn thận. Xem ví dụ câu trả lời này .
Ralf

Tôi không hiểu vấn đề là gì khi "$BCKGRND"đánh giá một cuộc tranh luận trống rỗng.
mosvy

2
@Ralf hoàn toàn không liên quan trong trường hợp này . Chẳng có gì đặc biệt về eval - chẳng hạn, bạn có thể thực thi các lệnh thông qua các mở rộng số học. Có lẽ nên có một cảnh báo như vậy đối với việc sử dụng bash (hoặc bất kỳ vỏ tương tự nào) ;-)
mosvy

1
@Kusalananda evalsẽ tham gia các đối số của nó với khoảng trắng trước khi thực hiện eval thực tế. Hãy thử nó : eval printf "'{%s}\n'" foo "" "" "". eval foo "" "" "" ""là hoàn toàn tương tự eval foo, không có vấn đề gì IFShay điều gì khác.
mosvy

1
Lệnh được đánh giá phải nằm trong dấu ngoặc kép nếu nó chứa bất kỳ ký tự đặc biệt nào, vd eval 'sleep $TIMEOUT' "$BACKGROUND". Nếu không, bạn có thể mở rộng gấp đôi nếu biến mở rộng sang biến khác hoặc chứa các ký tự đặc biệt. Ngoài ra, trích dẫn lồng nhau có thể nhận được khó khăn.
Barmar
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.