2010-09-10 46 views
30

làm cách nào tôi có thể thực hiện lệnh shell trong nền từ bên trong tập lệnh bash, nếu lệnh nằm trong chuỗi?thực hiện lệnh shell trong nền từ tập lệnh

Ví dụ:

#!/bin/bash 
cmd="nohup mycommand"; 
other_cmd="nohup othercommand"; 

"$cmd &"; 
"$othercmd &"; 

này không làm việc - làm thế nào tôi có thể làm điều này?

+2

Xem thêm [BashFAQ/050] (http://mywiki.wooledge.org/BashFAQ/050). –

Trả lời

32

Để lại tắt có dấu ngoặc kép

$cmd & 
$othercmd & 

ví dụ:

[email protected] /tmp 
$ cat test 
#!/bin/bash 

cmd="ls -la" 

$cmd & 


[email protected] /tmp 
$ ./test 

[email protected] /tmp 
$ total 6 
drwxrwxrwt+ 1 nicholas root 0 2010-09-10 20:44 . 
drwxr-xr-x+ 1 nicholas root 4096 2010-09-10 14:40 .. 
-rwxrwxrwx 1 nicholas None 35 2010-09-10 20:44 test 
-rwxr-xr-x 1 nicholas None 41 2010-09-10 20:43 test~ 
+2

cảm ơn. nó là cần thiết để rời khỏi dấu chấm phẩy quá xa như tôi có thể nói. – user248237dfsf

+0

Ngoài ra, hãy đảm bảo bạn không ** đặt dấu ngoặc kép quanh '$ cmd'. Nếu bạn làm như vậy, nó sẽ cố gắng chạy một lệnh gọi là '" ls -la "' thay vì 'ls' bằng các công tắc' -la'. – GreenRaccoon23

+0

'cmd = 'một số lệnh' với các đối số" '; $ cmd' không phải là ** ở tất cả ** giống như 'some-command 'với các đối số" '. Nó sẽ thất bại nếu bạn có trích dẫn trong danh sách đối số của bạn; nó sẽ thất bại nếu bạn cần phải kiểm soát khi globs được và không được mở rộng; nó sẽ thất bại nếu chạy mã phụ thuộc vào việc mở rộng cú đúp hoặc mở rộng tham số tại thời gian thực hiện. Xem [BashFAQ # 50] (http://mywiki.wooledge.org/BashFAQ/050): * Tôi đang cố gắng đặt lệnh trong một biến, nhưng các trường hợp phức tạp luôn thất bại! *. –

0

này hoạt động bởi vì đó là một biến tĩnh. Bạn có thể làm một cái gì đó mát nhiều như thế này:

filename="filename" 
extension="txt" 
for i in {1..20}; do 
    eval "filename${i}=${filename}${i}.${extension}" 
    touch filename${i} 
    echo "this rox" > filename${i} 
done 

Mã này sẽ tạo ra 20 file và động thiết lập 20 biến. Tất nhiên bạn có thể sử dụng một mảng, nhưng tôi chỉ cho bạn thấy tính năng :). Lưu ý rằng bạn có thể sử dụng các biến $ filename1, $ filename2, $ filename3 ... bởi vì chúng được tạo ra với lệnh đánh giá. Trong trường hợp này, tôi chỉ tạo các tệp, nhưng bạn có thể sử dụng để tạo các đối số động cho các lệnh và sau đó thực hiện trong nền.

22

Building tắt của câu trả lời ngoozeff 's, nếu bạn muốn thực hiện một lệnh chạy hoàn toàn trong nền (ví dụ, nếu bạn muốn giấu sản lượng của nóngăn ngừa nó khỏi bị giết khi bạn đóng nó thiết bị đầu cuối cửa sổ), bạn có thể làm điều này thay vì:

cmd="google-chrome"; 
"${cmd}" &>/dev/null &disown; 

& (người đầu tiên một) đã tách lệnh từ stdin.
>/dev/null detaches phiên làm việc phiên bản từ stdoutstderr.
&disown xóa lệnh khỏi danh sách công việc của vỏ .

Bạn cũng có thể sử dụng &! thay vì &disown; chúng đều là cùng một lệnh.

Ngoài ra, khi đặt một lệnh bên trong của một biến, nó thích hợp hơn để sử dụng eval "${cmd}" hơn "${cmd}":

cmd="google-chrome"; 
eval "${cmd}" &>/dev/null &disown; 

Nếu bạn chạy lệnh này trực tiếp tại ga, nó sẽ hiển thị các PID của quá trình mà lệnh bắt đầu. Nhưng bên trong tập lệnh shell, không có đầu ra sẽ được hiển thị.

Dưới đây là một chức năng cho nó:

#!/bin/bash 

# Run a command in the background. 
_evalBg() { 
    eval "[email protected]" &>/dev/null &disown; 
} 

cmd="google-chrome"; 
_evalBg "${cmd}"; 

http://felixmilea.com/2014/12/running-bash-commands-background-properly/

+1

@ user248237dfsf @ GreenRaccoon23 'eval" $ {cmd} "' chắc chắn tốt hơn nhiều so với chỉ '$ {cmd}'. Tôi tin rằng đó là những gì bạn có nghĩa là "$ {cmd}" 'sẽ thất bại cho các trường hợp như:' cmd = 'ls -l''. Ngoài ra, '$ {cmd}' chính nó không phải là giải pháp hoàn hảo vì nó sẽ thất bại cho các trường hợp sử dụng mở rộng được thực hiện trước khi mở rộng tham số. Vì vậy, ví dụ cho 'cmd = 'touch file {1..5}''. – PesaThe

+0

'eval" $ @ "' là lỗi - nếu ai đó mong đợi '" $ @ "' để đảm bảo rằng đối số được truyền riêng biệt với nhau, sử dụng 'eval' đánh bại điểm (bằng cách ghép tất cả các đối số của nó lại với nhau thành một chuỗi và sau đó đánh giá nó). Tốt hơn là * hoặc * sử dụng '" $ @ "' (các đối số dự kiến ​​sẽ được phân tách trước), hoặc 'eval" $ 1 "' (mong đợi chính xác một đối số được định dạng để phân tích cú pháp). –

+0

@CharlesDuffy Ví dụ về thời điểm 'eval" $ @ "' là lỗi? Tôi không thể nghĩ ra. Tôi có thể nghĩ về những trường hợp mà '" $ @ "' sẽ bị lỗi, giống như các biến gián tiếp. 'eval" $ {1} "' cũng sẽ bỏ qua nhiều đối số, như bạn đã chỉ ra. 'eval" $ @ "' sẽ xử lý cả hai trường hợp cạnh đó. Tôi đồng ý rằng 'eval '$ {1}" 'là đủ bởi vì mã của bạn phải nhất quán theo cách nó gọi hàm đó. Việc yêu cầu các dấu ngoặc kép trong '_evalBg '$ {cmd}" 'thay vì' _evalBg $ {cmd} 'sẽ làm cho mã dễ quản lý hơn trong thời gian dài. – GreenRaccoon23

0

Ví dụ, bạn có một chương trình bắt đầu được đặt tên chạy.sh để bắt đầu nó làm việc tại nền làm dòng lệnh sau đây. ./run.sh &>/dev/null &

Các vấn đề liên quan