Câu trả lời:
Sử dụng Kiểm soát công việc của bash để gửi quy trình vào nền:
bg
để chạy nó trong nền.disown -h [job-spec]
trong đó [job-spec] là số công việc (như %1
đối với công việc đang chạy đầu tiên; tìm về số của bạn bằng jobs
lệnh) để công việc không bị giết khi đóng thiết bị đầu cuối.disown -h
có lẽ đây là câu trả lời chính xác hơn: "làm cho sự thất vọng hành xử giống như nohup (tức là các công việc sẽ ở trong cây quy trình hiện tại của bạn cho đến khi bạn thoát khỏi vỏ của mình) Điều này cho phép bạn nhìn thấy tất cả các công việc mà cái vỏ này bắt đầu. " (từ [ quantprincipl.com/invest/index.php/docs/tipsandtricks/unix/ mẹo )
disown
, từ chối tạo một quy trình, có nghĩa là đầu vào / đầu ra tiêu chuẩn được chuyển hướng đến / dev / null. Vì vậy, nếu bạn có kế hoạch để không thừa nhận một công việc, nó tốt hơn để bắt đầu nó bằng cách đăng nhập vào một tập tin, ví dụmy_job_command | tee my_job.log
disown
tách bất kỳ đường ống từ quá trình. Để gắn lại ống, sử dụng gdb
như mô tả trong chủ đề này . Cụ thể hơn, bài này .
Giả sử vì một số lý do Ctrl+ Zcũng không hoạt động, hãy đi đến một thiết bị đầu cuối khác, tìm id quá trình (sử dụng ps
) và chạy:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
sẽ đình chỉ quá trình và SIGCONT
sẽ tiếp tục quá trình, trong nền. Vì vậy, bây giờ, đóng cả hai thiết bị đầu cuối của bạn sẽ không dừng quá trình của bạn.
disown %1
trong thiết bị đầu cuối trước khi đóng nó.
kwin
sau khi gặp sự cố mà không nghĩ đến hậu quả). Vì vậy, nếu tôi dừng kwin, mọi thứ sẽ đóng băng và tôi không có khả năng chạy bg
!
Lệnh để tách một công việc đang chạy khỏi shell (= làm cho nó không hoạt động) là disown
và một lệnh shell cơ bản.
Từ bash-manpage (man bash):
từ chối [-ar] [-h] [jobspec ...]
Không có tùy chọn, mỗi jobspec sẽ bị xóa khỏi bảng công việc đang hoạt động. Nếu tùy chọn -h được đưa ra, mỗi jobspec sẽ không bị xóa khỏi bảng, nhưng được đánh dấu để SIGHUP không được gửi đến công việc nếu shell nhận được SIGHUP. Nếu không có jobspec nào xuất hiện và cả tùy chọn -a hay -r đều được cung cấp, công việc hiện tại sẽ được sử dụng. Nếu không có jobspec nào được cung cấp, tùy chọn -a có nghĩa là loại bỏ hoặc đánh dấu tất cả các công việc; tùy chọn -r không có đối số jobspec sẽ hạn chế hoạt động đối với các công việc đang chạy. Giá trị trả về là 0 trừ khi một jobspec không chỉ định một công việc hợp lệ.
Điều đó có nghĩa là, đơn giản
disown -a
sẽ loại bỏ tất cả các công việc khỏi bảng công việc và làm cho chúng không hoạt động
disown -a
loại bỏ tất cả các công việc. Một đơn giản disown
chỉ loại bỏ công việc hiện tại. Như trang người đàn ông trong câu trả lời nói.
Đây là những câu trả lời tốt ở trên, tôi chỉ muốn thêm một sự làm rõ:
Bạn không thể disown
là một mánh khóe hay quá trình, disown
một công việc, và đó là một sự khác biệt quan trọng.
Một công việc là một cái gì đó là một khái niệm của một quá trình được gắn vào một vỏ, do đó bạn phải ném công việc vào nền (không đình chỉ nó) và sau đó từ chối nó.
Vấn đề:
% jobs
[1] running java
[2] suspended vi
% disown %1
Xem http: //www.quantprincipl.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ để thảo luận chi tiết hơn về Unix Job Control.
Thật không may disown
là cụ thể cho bash và không có sẵn trong tất cả các shell.
Một số hương vị nhất định của Unix (ví dụ AIX và Solaris) có một tùy chọn trên nohup
chính lệnh có thể được áp dụng cho một quy trình đang chạy:
nohup -p pid
AIX
và Solaris
. "Các phiên bản AIX và Solaris của nohup có tùy chọn -p sửa đổi quy trình đang chạy để bỏ qua các tín hiệu SIGHUP trong tương lai. Không giống như bản dựng sẵn được mô tả ở trên của bash, nohup -p chấp nhận ID tiến trình.". Nguồn
Câu trả lời của Node thực sự rất hay, nhưng nó bỏ ngỏ câu hỏi làm thế nào để có thể chuyển hướng xuất chuẩn và thiết bị xuất chuẩn. Tôi đã tìm thấy một giải pháp trên Unix & Linux , nhưng nó cũng chưa hoàn thành. Tôi muốn hợp nhất hai giải pháp này. Đây là:
Đối với thử nghiệm của mình, tôi đã tạo ra một tập lệnh bash nhỏ có tên loop.sh, nó in bản thân của nó với một phút ngủ trong một vòng lặp vô hạn.
$./loop.sh
Bây giờ có được PID của quá trình này bằng cách nào đó. Thường ps -C loop.sh
là đủ tốt, nhưng nó được in trong trường hợp của tôi.
Bây giờ chúng ta có thể chuyển sang một thiết bị đầu cuối khác (hoặc nhấn ^ Z và trong cùng một thiết bị đầu cuối). Bây giờ gdb
nên được gắn liền với quá trình này.
$ gdb -p <PID>
Điều này dừng tập lệnh (nếu đang chạy). Trạng thái của nó có thể được kiểm tra bởips -f <PID>
, trong đó STAT
trường là 'T +' (hoặc trong trường hợp ^ Z 'T'), có nghĩa là (man ps (1))
T Stopped, either by a job control signal or because it is being traced
+ is in the foreground process group
(gdb) call close(1)
$1 = 0
Đóng (1) trả về số 0 khi thành công.
(gdb) call open("loop.out", 01102, 0600)
$6 = 1
Mở (1) trả về bộ mô tả tệp mới nếu thành công.
Điều này mở bằng với open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
. Thay vì O_RDWR
O_WRONLY
có thể được áp dụng, nhưng/usr/sbin/lsof
nói 'u' cho tất cả các trình xử lý tệp std * ( FD
cột) O_RDWR
.
Tôi đã kiểm tra các giá trị trong tệp tiêu đề /usr/include/bits/fcntl.h.
Các tập tin đầu ra có thể được mở bằng O_APPEND
, nhưnohup
sẽ làm, nhưng điều này không được đề xuất bởi man open(2)
, vì các vấn đề NFS có thể xảy ra.
Nếu chúng ta lấy -1 làm giá trị trả về, thì sẽ call perror("")
in thông báo lỗi. Nếu chúng ta cần errno, sử dụngp errno
gdb comand.
Bây giờ chúng ta có thể kiểm tra tệp mới được chuyển hướng. /usr/sbin/lsof -p <PID>
in:
loop.sh <PID> truey 1u REG 0,26 0 15008411 /home/truey/loop.out
Nếu chúng ta muốn, chúng ta có thể chuyển hướng stderr sang một tệp khác, nếu chúng ta muốn sử dụng call close(2)
và call open(...)
sử dụng lại tên tệp khác.
Bây giờ phần đính kèm bash
phải được phát hành và chúng tôi có thể thoát gdb
:
(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
Nếu đoạn script bị dừng bởi gdb
một thiết bị đầu cuối khác, nó sẽ tiếp tục chạy. Chúng ta có thể chuyển trở lại terminal của loop.sh. Bây giờ nó không ghi bất cứ điều gì lên màn hình, nhưng chạy và ghi vào tệp. Chúng ta phải đặt nó vào nền. Vì vậy, nhấn ^Z
.
^Z
[1]+ Stopped ./loop.sh
(Bây giờ chúng tôi ở trong trạng thái như thể ^Z
được nhấn vào lúc đầu.)
Bây giờ chúng ta có thể kiểm tra trạng thái của công việc:
$ ps -f 24522
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
$ jobs
[1]+ Stopped ./loop.sh
Vì vậy, quá trình nên được chạy trong nền và tách ra khỏi thiết bị đầu cuối. Số trong jobs
đầu ra của lệnh trong ngoặc vuông xác định công việc bên trong bash
. Chúng ta có thể sử dụng các bash
lệnh được tích hợp sẵn sau đây áp dụng dấu '%' trước số công việc:
$ bg %1
[1]+ ./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
Và bây giờ chúng ta có thể thoát khỏi bash gọi. Quá trình tiếp tục chạy trong nền. Nếu chúng ta thoát PPID của nó trở thành quá trình 1 (init (1)) và thiết bị đầu cuối điều khiển trở nên không xác định.
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID> 1 0 11:16 ? S 0:00 /bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>
...
loop.sh <PID> truey 0u CHR 136,36 38 /dev/pts/36 (deleted)
loop.sh <PID> truey 1u REG 0,26 1127 15008411 /home/truey/loop.out
loop.sh <PID> truey 2u CHR 136,36 38 /dev/pts/36 (deleted)
BÌNH LUẬN
Các công cụ gdb có thể được tự động hóa tạo một tệp (ví dụ loop.gdb) có chứa các lệnh và chạy gdb -q -x loop.gdb -p <PID>
. Loop.gdb của tôi trông như thế này:
call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit
Hoặc người ta có thể sử dụng một lớp lót sau đây để thay thế:
gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>
Tôi hy vọng đây là một mô tả khá đầy đủ về giải pháp.
lsof
(tên của tay cầm tệp pipe
, không giống như /dev/pts/1
) hoặc bởi ls -l /proc/<PID>/fd/<fd>
(điều này hiển thị liên kết tượng trưng của tay cầm). Ngoài ra các quy trình con vẫn có thể không được chuyển hướng đầu ra, mà nên được chuyển hướng đến một tệp.
Để gửi quy trình chạy tới nohup ( http://en.wikipedia.org/wiki/Nohup )
nohup -p pid
, nó không làm việc cho tôi
Sau đó, tôi đã thử các lệnh sau và nó hoạt động rất tốt
Chạy một số SOMECOMMAND, nói /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
.
Ctrl+ Zđể dừng (tạm dừng) chương trình và quay lại trình bao.
bg
để chạy nó trong nền.
disown -h
để quá trình không bị chết khi thiết bị đầu cuối đóng cửa.
Gõ exit
để thoát ra khỏi vỏ vì bây giờ bạn rất tốt vì thao tác sẽ chạy trong nền trong quy trình riêng của nó, vì vậy nó không bị ràng buộc với vỏ.
Quá trình này là tương đương với chạy nohup SOMECOMMAND
.
bg
- điều này sẽ đặt công việc trong nền và trở lại trong quá trình chạydisown -a
- điều này sẽ cắt tất cả các tệp đính kèm với công việc (vì vậy bạn có thể đóng thiết bị đầu cuối và nó vẫn sẽ chạy)Các bước đơn giản này sẽ cho phép bạn đóng thiết bị đầu cuối trong khi vẫn duy trì quá trình chạy.
Nó sẽ không được đưa vào nohup
(dựa trên sự hiểu biết của tôi về câu hỏi của bạn, bạn không cần nó ở đây).
Điều này làm việc cho tôi trên Ubuntu linux trong khi ở tcshell.
CtrlZ tạm dừng nó
bg
chạy trong nền
jobs
để có được số công việc của nó
nohup %n
Trong đó n là số công việc
nohup: failed to run command '%1': No such file or directory
yourExecutable &
và các đầu ra tiếp tục xuất hiện trên màn hình vàCtrl+C
dường như không dừng lại bất cứ điều gì, chỉ cần gõdisown;
và nhấn một cách mù quángEnter
ngay cả khi màn hình đang cuộn với đầu ra và bạn không thể thấy gì bạn đang gõ Quá trình sẽ bị từ chối và bạn sẽ có thể đóng thiết bị đầu cuối mà không bị quá trình chết.