Sự khác biệt giữa Ctrl-Z và kill -STOP là gì?


14

Khi tôi chạy một lệnh ( maketrên một dự án lớn) từ shell, tôi có thể gõ Ctrl-Z để dừng quá trình và quay lại shell. Sau đó, tôi có thể chạy fgđể tiếp tục quá trình.

Tôi đang cố gắng viết một kịch bản shell để tự động hóa điều này (cụ thể là kiểm tra nhiệt độ CPU của tôi vài giây một lần và dừng quá trình nếu nó quá nóng, vì máy tính của tôi dễ bị quá nóng). Nỗ lực đầu tiên của tôi hoạt động như thế này (đơn giản hóa):

make &
subpid="$!"

sleep 2
# If the CPU temperature is too high...
kill -STOP "$subpid"

sleep 2
# If the CPU temperature has dropped to safe levels...
kill -CONT "$subpid"

wait "$subpid"

Thật không may, điều này đã không làm việc; gửi SIGSTOP đến quá trình đã không tạm dừng nó (như đã thấy rõ bằng cách tiếp tục gửi đầu ra đến thiết bị đầu cuối). Tôi đã chạy make &ở dòng lệnh, gửi SIGSTOP và kiểm tra trạng thái quá trình với ps; nó được liệt kê là đã dừng (và bắt đầu lại khi tôi gửi SIGCONT), nhưng nó vẫn tăng sản lượng và tăng nhiệt độ cốt lõi của tôi! Dừng nó bằng Ctrl-Z không bao giờ có vấn đề này, nhưng tôi không biết làm thế nào để thực hiện điều đó trong một tập lệnh.

Điều gì làm cho Ctrl-Z khác với kill -STOPvà làm cách nào tôi có thể có hành vi của cái trước trong tập lệnh shell?


Và vâng, makeđang được chạy đệ quy. Trong thực tế, tôi nghĩ rằng nó đi sâu một vài cấp độ.
Taymon

Câu trả lời:


12

Điều gì làm cho Ctrl-Z khác với kill -STOPvà làm cách nào tôi có thể có hành vi của cái trước trong tập lệnh shell?

CTRL-Zthường gửi SIGTSTP (có thể bị chặn) và - ngoài những thứ khác - shell thường đặt lại tty về trạng thái đã lưu trước đó trong những dịp này. Tuy nhiên, quan trọng hơn, nhóm quy trình thiết bị đầu cuối kiểm soát được đặt thành PID của shell (và sau đó lại là một PID của công việc được nối lại fg).

Quay lại vấn đề ban đầu của bạn: sử dụng thang đo tần số phụ thuộc nhiệt độ, ví dụ như Cpufreqd có thể thực sự là một cái búa tốt hơn cho móng tay của bạn.


4

Bạn không muốn dừng makequá trình; bạn muốn dừng makequá trình tất cả các tiến trình con của nó. Tôi đặt cược làm đã được chạy đệ quy.

Bạn có thể thử set -m, sau đó sử dụng %1thay vì "$subpid".

Việc bật set -m"điều khiển công việc", được tắt theo mặc định bên trong các tập lệnh. Tôi nghĩ rằng nó nên hoạt động cho trường hợp sử dụng của bạn, mặc dù mọi người dường như nghĩ rằng đó là một ý tưởng tồi nói chung .


4

Bạn có thể gửi tín hiệu đến tất cả các quy trình trong một nhóm quy trình nếu bạn chỉ định giá trị PID âm - PGID của người lãnh đạo phiên.

kill -STOP -"$subpid"

Lưu ý: Để chạy chương trình trong phiên mới, hãy sử dụng setsid make . Nhưng trong trường hợp của bạn tôi nghĩ rằng nó không cần thiết. Tuy nhiên, nếu make được chạy đệ quy, mỗi phiên bản của make có thể là người lãnh đạo của chính nó (tôi không chắc về điều đó).

Một lựa chọn khác có thể là sử dụng killall:

killall -STOP make

Sự khác biệt giữa Ctrl + Z và kill -STOP:

  • Ctrl-Z thực sự gửi TSTP, có thể bị chặn.
  • DỪNG không thể bị chặn.

Cách tiếp cận PGID không hoạt động và tạo ra dòng đầu ra sau : /usr/local/bin/myscript: line 38: kill: (-10202) - No such process. Các quá trình nền tiếp tục chạy. Tôi không nghĩ rằng killallphương pháp này sẽ hiệu quả vì một số quy trình con có vẻ shđúng hơn make.
Taymon

Có vẻ như quá trình bạn đang gửi tín hiệu đã hoàn thành. Các quy trình con có tên sh được sinh ra bởi make. Trong trường hợp của bạn thực hiện và nhiều quy trình con, tốt nhất có thể là có được các bộ vi xử lý của tất cả trẻ em và DỪNG tất cả chúng.
Jurij

Nó đã kết thúc hoạt động khi tôi thực hiện thủ công từ trình bao, nhưng không phải trong tập lệnh shell. Tôi nghĩ điều này là bởi vì khi tôi thực hiện thủ công, bộ mã gốc (mà những cái khác được thừa hưởng PGID của họ) là của makelệnh đầu tiên , nhưng khi tôi thực hiện nó từ tập lệnh, thì bộ mã gốc là từ chính tập lệnh shell .
Taymon

1

Ctrl+ Cđược sử dụng để giết một quá trình với tín hiệu SIGINT, hay nói cách khác đó là giết một cách lịch sự .

Ctrl+ Z được sử dụng để tạm dừng một quá trình bằng cách gửi tín hiệu SIGSTP , giống như tín hiệu ngủ, có thể được hoàn tác và quá trình có thể được nối lại.

Tuy nhiên, khi một quá trình bị đình chỉ, chúng ta có thể tiếp tục lại nó bằng cách fg (tiếp tục ở nền trước)bg (tiếp tục ở chế độ nền) , nhưng tôi không thể tiếp tục quá trình bị giết, đó là một sự khác biệt giữa việc sử dụng Ctrl+ C& Ctrl+ Z.

Làm thế nào để xem quá trình bị đình chỉ?

Khi bạn có nhiều lệnh bị treo, để liệt kê chúng, bạn sử dụng jobslệnh và đầu ra sẽ là:

[1]-  Stopped                 cat
[2]+  Stopped                 vi

Làm thế nào để giết một quá trình bị đình chỉ trong nền?

Bằng cách sử dụng killlệnh:

kill %nTrong đó n là số công việc (một trong ngoặc vuông từ đầu ra công việc), vì vậy tôi muốn giết mèo : kill %1.

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.