Không thể giết một tiến trình đang chạy mà dường như không thể thấy được trong trình quản lý tác vụ


6

Tôi đã khởi động một ứng dụng sẽ không chạy, nhưng tôi không thể xóa nó vì nó vẫn đang chạy. Tôi có thể in PID, nhưng không giết được quá trình sử dụng nó.

~ $ ps ax | grep snappr | awk '{print $1}'
70824
~ $ kill $(ps ax | grep snappr | awk '{print $1}')
-bash: kill: (70832) - No such process

@BeowulfOF: "Đặt hàng đầu ra ps"? Huh? điều đó có nghĩa gì? Nếu snapprđang chạy, lệnh đầu tiên sẽ liệt kê hai PID: đó là snapprvà của grep- như đã giải thích trong câu trả lời của tôi, mà tôi đã đăng nửa giờ trước khi bạn đăng bình luận này. ... ... ... ... ... PS Bạn có thể muốn đọc lại các đóng góp của mình tốt hơn một chút ("Tôi là các trạng thái lỗi", "quảng cáo", "mit").
Scott

Xin lỗi Scott, những sai lầm đến từ sự tự kỷ, tôi đã viết nó ngắn gọn từ điện thoại di động của tôi. Không có lý do, đó là lý do tại sao tôi xóa bình luận.
Oliver Friedrich

4
Của bạn grep snapprlà phù hợp với quá trình grep snappr.
Sobrique

Nền tảng gì? Mac OS X? Linux? Cygwin?
Peter Mortensen

Câu trả lời:


17

Bạn có nhận thấy rằng bạn có hai PID khác nhau trong hai lần thử không?

Xem xét điều này: nếu bạn gõ một lệnh như thế vi raven.txt, thì ps axsẽ hiển thị một dòng hiển thị lệnh vi raven.txt. Tương tự, nếu bạn gõ một lệnh như thế grep snappr, thì nó ps axsẽ hiển thị một dòng hiển thị lệnh grep snappr. Và, nếu bạn dẫn đầu ra của psthông qua đó grep snappr, grepsẽ tìm thấy dòng mô tả chính nó . Vì vậy, nếu bạn gõ

$ ps ax | grep snappr | awk '{print $1}'

lặp đi lặp lại, nó sẽ in một số khác nhau mỗi lần (vì nó in ra PID grepvà bạn sẽ có một grepquy trình mới, duy nhất mỗi khi bạn chạy lệnh).

Cuối cùng, hãy xem xét: killlệnh không thể được thực thi cho đến khi (các) đối số của nó được biết. Để biết được đối số của nó, $(ps ax | grep snappr | awk '{print $1}')đường ống phải được hoàn thành. Điều này ngụ ý rằng grepphải chấm dứt 1 . Do đó, việc killđược đưa ra quy trình PID của grepquy trình, nhưng chỉ sau khi grepquy trình kết thúc - do đó, một cách tự nhiên, nó báo cáo "Không có quy trình như vậy".

Có lẽ tôi nên đề cập rằng không có snapprquá trình chạy. Nếu có, lệnh đầu tiên của bạn sẽ xuất ra hai số: PID của snapprvà PID của grep snappr. Bây giờ, nếu snapprđang chạy, lệnh của bạn có thể bắt đầu chạy bán chính xác, ý tôi là nó làm những gì bạn muốn nhưng cũng đưa ra một thông báo lỗi. Nếu snapprnó đang chạy với PID 42097 và grep snapprchạy với PID 70848, thì killlệnh sẽ là kill 42097 70858, nó sẽ giết snappr và nhận thông báo lỗi từ việc cố gắng giết grepquá trình không còn tồn tại.

Có lẽ bạn sẽ muốn cải thiện điều này. Cách yêu thích của tôi, mà tôi đã phát minh ra cách đây 20 năm, nó là để thay đổi grepthành grep "[s]nappr", sẽ phù hợp snapprnhưng sẽ không khớp với chính nó. Một cách tiếp cận khác là sử dụng pgrepchứ không phải ps | grep.


1 Ngoài ra, awkcó thể kết thúc nếu grepchỉ đóng thiết bị xuất chuẩn của nó. Đây sẽ là hành vi rất bất thường đối với chương trình * nix.


Tôi có một tập lệnh bash mà tôi chỉ muốn chạy một lần trên máy của mình. Trong tập lệnh tôi sử dụng mã này để kiểm tra (trong đó $ THIS là tên của tập lệnh) : PRIOR="$(ps --no-headers -Ao "pid,ppid,sid,args"|grep "$THIS"|grep -Ev "(grep |$PPID |$$ |<defunct>)")". Nếu $ PRIOR không null thì tập lệnh đã chạy. Tôi đã có nhiều thành công với điều này hơn là với pgrep.
gogoud

À, vâng, grep | grep -vgiải pháp cũ . Tại sao phải chạy một quy trình bổ sung mà bạn không cần? Làm việc thông minh hơn chứ không chăm chỉ hơn.
Scott

Tôi đồng ý nó trông lộn xộn. Tôi rất vui khi tìm thấy một cách tốt hơn, đáng tin cậy. ps -C không bắt được tất cả các quy trình, pgrep bao gồm các quy trình không còn tồn tại.
gogoud

(1) Bạn có biết bất kỳ vấn đề với grep "[s]nappr"giải pháp của tôi ? (2) Miễn là chúng ta đang nói về các quy trình tiêu diệt, ai quan tâm liệu các quy trình không còn tồn tại có được bao gồm không? Giết một quá trình không còn tồn tại là không có.
Scott

Tôi nhận ra chúng ta đang lạc đề ở đây. Tôi thích [s] giải pháp ngủ trưa của bạn! Nhưng tôi cần loại trừ các khoản giảm giá vì tôi thực sự muốn biết liệu có một quy trình trực tiếp ngoài đó (trong trường hợp đó, dừng ngay bây giờ!) Hoặc chỉ một cái gì đó sắp chết. Và tôi không chỉ cần loại trừ lệnh gọi grep mà tôi cũng cần loại trừ thể hiện đang chạy của chính tập lệnh ($$) và có thể là cha mẹ đã gọi nó ($ PPID).
gogoud

8

Câu trả lời ngắn hơn

Đừng nhảy qua hoops Bash để giết snapprvới ps, đường ống thông qua grepvà sau đó cấp nước tập trung thông qua awknhư thế. Thay vào đó hãy cố gắng giết nó như thế này bằng cách sử dụng pkill; không ồn ào hay ồn ào và nó nhắm mục tiêu dựa trên tên quá trình ra khỏi hộp:

sudo pkill snappr

Câu trả lời dài hơn

Không quá rõ ràng về cách Snapper hoạt động ở cấp độ quy trình hệ thống, nhưng vấn đề có thể là bạn chỉ lấy ID tiến trình con thay vì ID tiến trình cha.

Trong thực tế, tôi tin rằng phương thức bạn đang sử dụng để lấy ID tiến trình ( ps ax | grep snappr | awk '{print $1}') sẽ trả về toàn bộ danh sách ID tiến trình được kết nối với snapprbất kể đó là cha mẹ hay con. Vì vậy, bằng cách sử dụng, bạn có thể giết một ID tiến trình chỉ là ID tiến trình con nhưng ID cha vẫn sẽ hoạt động và có thể tạo ra một quy trình con khác để bù đắp.

Vì vậy, có lẽ bạn có thể làm một cái gì đó như thế này để lấy ID cha dứt khoát của bất kỳ ID tiến trình nào bạn cung cấp và hành động theo nó; bằng chứng đơn giản về khái niệm về cách thức hoạt động của nó:

ps -p [process ID] -o ppid=

Chạy lệnh trần đó trong Bash sẽ cung cấp cho bạn ID tiến trình cha của ID tiến trình con mà bạn đặt [process ID]. Vì vậy, nếu ID con 4567có ID tiến trình cha 123thì lệnh sẽ là:

ps -p 4567 -o ppid=

Và điều đó sẽ trở lại 123.

Điều đó nói rằng, đây có thể là một cách nguy hiểm để xử lý một quy trình đi lạc vì nếu tập lệnh của bạn lấy ID tiến trình cha mẹ thực tế snapper, thì cha mẹ của ID tiến trình đó thực sự có thể là vỏ Bash của riêng bạn. Vì vậy, bạn có thể vô tình giết chết vỏ Bash của mình thay vì snapperđánh bật bạn khỏi hệ thống trong khi để snapperquá trình chạy.

Nhưng tất cả những gì đã nói, tại sao không làm cho cuộc sống của bạn dễ dàng hơn và chỉ chạy pkillnhư thế này:

sudo pkill snappr

Điều đó sẽ giết tất cả các quá trình được kết nối snapprmà không có bất kỳ dòng lệnh ưa thích nào.


1
Tất nhiên, nếu bạn đang cố gắng giết một quá trình mà bạn đã bắt đầu (như đã nêu trong câu hỏi), miễn là nó không được thiết lập, bạn sở hữu quy trình đó và bạn không cần sudo. Và bạn không nên sử dụng sudonếu bạn không cần.
Scott

2
Nhiều khả năng - quá trình không thực sự tồn tại, grepđang khớp chính nó.
Sobrique

sử dụng killallthay vì pkilltừ mặc định pkillquá mức cần thiết.
Hongxu Chen
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.