2012-03-29 7 views
7

Sau khi cố gắng tìm ra lý do tại sao nhiệm vụ Capistrano (cố gắng khởi động một daemon ở chế độ nền) bị treo, tôi phát hiện rằng sử dụng && trong bash over ssh ngăn chương trình tiếp theo chạy trong lý lịch. Tôi đã thử nó trên bash 4.1.5 và 4.2.20.bash && nhà điều hành ngăn chặn backgrounding trên ssh

Sau đây sẽ treo (tức là chờ sleep để kết thúc) trong bash:

ssh localhost "cd /tmp && nohup sleep 10 >/dev/null 2>&1 &" 

Sau đây sẽ không:

ssh localhost "cd /tmp ; nohup sleep 10 >/dev/null 2>&1 &" 

Cả sẽ này:

cd /tmp && nohup sleep 10 >/dev/null 2>&1 & 

Cả zsh và dấu gạch ngang sẽ thực thi nó trong nền trong mọi trường hợp, bất kể && và ssh. Đây có phải là hành vi bình thường/mong đợi đối với bash hoặc lỗi không?

+1

tôi không chính xác biết câu trả lời cho câu hỏi của bạn, nhưng sẽ nói rằng đôi khi tôi gặp phải những kích thích tương tự khi sử dụng SSH, với Bash trên đầu từ xa. Tôi không biết liệu vấn đề có phải là đặc thù của Bash hay không, nhưng đôi khi tôi có may mắn hơn bằng cách sử dụng nội trang 'disown' của Bash shell chứ không phải lệnh' nohup'. Nếu điều này làm bạn quan tâm, hãy gõ 'help disown | ít hơn trong khi chạy Bash. Và nếu bạn tình cờ tìm hiểu một giải pháp chung, hãy đăng nó ở đây. Tôi nên quan tâm để đọc. – thb

+0

Tôi thực sự đã cố gắng mucking về với sự kết hợp khác nhau của 'disown',' nohup' và chuyển hướng, không có kết quả. Các '&&' luôn luôn bị cấm nền. Tôi có thể lấy đi bằng cách gói hai lệnh trong một vỏ bọc, nhưng điều đó không thực sự giống nhau. – Hinrik

+0

Lệnh này có vẻ phù hợp với tôi. Bạn có ý gì khi bị treo cổ? Liệu 'cd' mất một thời gian dài? Nó có thể là một vấn đề với máy chủ từ xa, ví dụ: quá tải. – suvayu

Trả lời

4

Một giải pháp dễ dàng là sử dụng:

ssh localhost "(cd /tmp && nohup sleep 10) >/dev/null 2>&1 &" 

(điều này cũng hoạt động nếu bạn sử dụng niềng răng, xem ví dụ thứ hai dưới đây).

Tôi không thử nghiệm thêm nhưng tôi đã thuyết phục hợp lý rằng nó phải làm với các mô tả tệp mở đang treo xung quanh. Có lẽ zsh và dấu gạch ngang ràng buộc && để điều này có nghĩa là những gì đã được đánh vần như:

{ cd /tmp && nohup sleep 10; } >/dev/null 2>&1 

trong bash.


Không, thử nghiệm nhanh trong dấu gạch ngang cho thấy rằng echo foo && echo bar >file chỉ chuyển hướng sau này. Tuy nhiên, nó phải có một cái gì đó để làm với kéo dài của fd mở gây ra ssh để chờ đợi cho đầu ra nhiều hơn; Tôi đã chạy vào điều này rất nhiều trong quá khứ. Thêm một mẹo nữa, không cần thiết nếu bạn sử dụng dấu ngoặc đơn hoặc dấu ngoặc ôm cho trường hợp cụ thể này nhưng có thể hữu ích trong bối cảnh chung hơn, nơi tập hợp các lệnh cần thực hiện với && phức tạp hơn. Vì bash dường như được treo trên bộ mô tả tệp không phù hợp với && nhưng không phải với ;, bạn có thể biến a && b && c thành a || exit 1; b || exit 1; c. Này làm việc với các trường hợp thử nghiệm:

ssh localhost "true || exit 1; echo going on; nohup sleep 10 >/dev/null 2>&1 &" 

Thay true với false và tiếng vang của "xảy ra" được bỏ qua.

(Bạn cũng có thể set -e, mặc dù đôi khi đó là một cái búa lớn hơn mong muốn.)

+0

Vâng, thay thế '&& 'bằng' || thoát 1; 'chắc chắn là giải pháp để sử dụng. – Hinrik

1

Điều này dường như làm việc:

ssh localhost "(exec 0>&- ; exec 1>&-; exec 2>&-; cd /tmp; sleep 20&)" 
+1

Hạn chế để đóng tất cả các mô tả lên phía trước là bạn không thể phát ra thông báo lỗi về máy chủ gốc ('ssh'). – torek