Làm thế nào tôi có thể yêu cầu ps
chỉ hiển thị các quy trình người dùng và không phải các luồng nhân?
Xem câu hỏi này để xem tôi muốn nói gì ...
Làm thế nào tôi có thể yêu cầu ps
chỉ hiển thị các quy trình người dùng và không phải các luồng nhân?
Xem câu hỏi này để xem tôi muốn nói gì ...
Câu trả lời:
Điều này nên làm (trong Linux):
ps --ppid 2 -p 2 --deselect
kthreadd
(PID 2) có PPID 0 ( trên Linux 2.6+ ) nhưng ps
không cho phép lọc PPID 0; do đó, công việc này
kthreadd
, sau đó xây dựng ps
cuộc gọi theo . Làm thế nào đảm bảo rằng điều này sẽ "luôn luôn" được gọi là "kthreadd"? Một giải pháp an toàn sẽ phức tạp hơn, chạy ps
bình thường và phân tích đầu ra, có thể thực hiện một số thử nghiệm.
x
cờ không hoạt động với cái này. ps au --ppid 2 -p 2 --deselect
hoạt động tốt.
Một cách để nhận ra các quy trình hạt nhân là họ không sử dụng bất kỳ bộ nhớ người dùng nào, vì vậy trường vsz là 0. Điều này cũng bắt được zombie (nhờ Stephane Chazelas cho quan sát này), có thể được loại bỏ dựa trên trạng thái của họ.
ps axl | awk '$7 != 0 && $10 !~ "Z"'
Để liệt kê chỉ các PID:
ps -e -o pid= -o state= -o vsize= | awk '$2 != "Z" && $3 != 0 {print $1}'
Trong thực tế tôi đã tìm thấy thành ngữ sau đây đủ:
ps auxf | grep -v ]$
Nó lọc các dòng kết thúc bằng dấu ngoặc, có thể dẫn đến bỏ sót các mục không mong muốn nhưng rất khó xảy ra. Đổi lại, nó khá dễ nhớ và gõ tương đối nhanh.
Một số quy trình như avahi-daemon thêm vào thông tin tên quy trình của họ trong ngoặc (tên máy chủ trong trường hợp avahi-daemon) và sẽ được lọc ra bằng lệnh này.
Một trong những đặc biệt của các quy trình đó là chúng không được hỗ trợ bởi một tệp thực thi, vì vậy bạn có thể làm ( trong zsh ):
ps /proc/[0-9]*/exe(^-@:h:t)
Hoặc với bất kỳ vỏ POSIX nào:
ps -p "$(find -L /proc/[0-9]*/exe ! -type l | cut -d / -f3 | paste -sd , -)"
Đó là kiểm tra các quá trình có /proc/<pid>/exe
liên kết đến một tệp.
Nhưng điều đó có nghĩa là bạn cần phải là siêu người dùng để có thể kiểm tra trạng thái của /proc/<pid>/exe
liên kết tượng trưng.
Chỉnh sửa : Khi điều đó xảy ra, các quá trình zombie (ít nhất) thỏa mãn điều kiện tương tự, vì vậy nếu bạn không muốn loại trừ chúng, bạn phải thêm lại chúng. Như:
ps -p "$(
{ find -L /proc/[0-9]*/exe ! -type l | cut -d / -f3
ps -Ao pid=,state= | sed -n 's/ Z//p'
} | paste -sd , -)"
Lưu ý rằng ps -f
hiển thị các tên quy trình đó trong ngoặc vuông không phải vì chúng là các quy trình hạt nhân, mà vì chúng có một khoảng trống argv[]
(vì vậy ps hiển thị tên quy trình thay vì argv[0]
ở đó). Bạn cũng có thể có một quy trình không gian người dùng với một khoảng trống argv[]
và bạn có thể có một tên quy trình với một argv[0]
hình thức [some-string]
để việc lọc ps
đầu ra dựa trên các dấu ngoặc vuông đó không phải là một lựa chọn hoàn hảo.
zsh
cú pháp. Thứ hai là cú pháp POSIX sh
( ps
và find
và cut
và paste
) tiêu chuẩn . Tất nhiên /proc
không được chỉ định bởi POSIX.
wc -l
). Chà, sau đó tôi sẽ chấp nhận câu trả lời của Hauke Laging , và đưa cho bạn một upvote. ;)
Bạn cũng có thể phân tích cú pháp ps
đầu ra và tìm tên quy trình không có trong ngoặc:
ps aux | awk '$NF!~/^\[.+\]$/'
awk -F: '$7 ~ home { print $1 }' /etc/passwd
- nhưng bạn vẫn sẽ nhận được các quy trình đề cập đến bất kỳ tên người dùng nào như vậy và bạn sẽ để lại tệp tạm thời. Tôi sẽ rút downvote của tôi, nhưng chỉ vì giải pháp thứ ba của bạn là hợp lý.
$NF
là từ cuối cùng của dòng lệnh trong ps aux
đầu ra. Các quy trình không hạt nhân có thể có [...]
ở đó. Như tôi đã nói trong câu trả lời của mình, [xxx]
ký hiệu không phải vì chúng là các tiến trình kernel, mà bởi vì chúng không có dòng lệnh (không có đối số) cũng được phép cho các quá trình không phải kernel.
Đối với bất kỳ ai đang thử điều này trong busybox, nơi ps
được đơn giản hóa nhiều và đầu ra khác nhau, biến thể câu trả lời tuyệt vời này của Gilles hoạt động tốt:
ps -o pid,user,comm,vsz,stat | awk '$4 != 0 && $5 !~ "Z"'
Theo câu trả lời của Gilles, phương pháp luận ở đây là tìm các quy trình không sử dụng bất kỳ bộ nhớ người dùng nào (`vsz col == 0) và lọc ra các quy trình zombie (trạng thái col không phải là 'Z').
Các cột đầu ra có thể được điều chỉnh dễ dàng, miễn là số trường awk dựa trên 1 được điều chỉnh tương ứng. Xem các tùy chọn mà ps của bạn có sẵn bằng cách đưa vào một giá trị không có thật và nó sẽ cho bạn biết. Ví dụ:
$ ps -o foo
ps: bad -o argument 'foo', supported arguments: user,group,comm,args,pid,ppid,pgid,tty,vsz,stat,rss
Nếu bạn chỉ cần số đếm ... Tôi có nhu cầu tương tự để lọc hạt nhân so với quy trình người dùng, nhưng tôi chỉ cần số lượng tương ứng của từng loại. Đây là giải pháp của tôi:
ps -eo vsize | awk '{p[$1==0]++} END {printf "%-16s %6d\n%-16s %6d\n%-16s %6d\n", "Kernel processes", p[1], "User processes", p[0], "Total processes", p[0]+p[1]}'
Đầu ra mẫu :
Kernel processes 353
User processes 52
Total processes 405
Giải thích : Tôi đang sử dụng bản hack rằng các quy trình VSZ = 0 có thể được coi là các quy trình kernel. Vì vậy, với awk
, tôi đánh giá một so sánh trên VSZ (từ ps -eo vsize
), cho dù nó bằng không. Kết quả của phép so sánh sẽ là boolean 0 hoặc 1. Tôi tạo một mảng p[]
và khi tôi chạy xuống danh sách các quy trình, nếu đó là một quá trình kernel, tôi sẽ tăng lên p[1]++
. Nếu không, như quá trình người dùng, tôi tăng lên p[0]++
. Sau khi tăng tất cả, tôi dán nhãn và in các giá trị (nghĩa là đếm) cho p [0] và p [1] trong END { }
khối.
Những gì bạn đang tìm kiếm, bạn của tôi, không phải ps
, nhưng pstree
.
Đầu tiên, xác định quá trình kernel đầu tiên. PID của nó thường là 1 trên hệ thống không có systemd và 2 với systemd.
Sau đó sử dụng lệnh này:
$ pstree -p <1 or 2> | grep -o '([0-9]\+)' | grep -o '[0-9]\+'
Câu trả lời được chọn (một với) đang sử dụng lệnh khác:
$ ps --ppid 2 -p 2 --deselect
Vấn đề với ps
lệnh này là nó chỉ bao gồm những đứa trẻ trực tiếp chứ không phải tất cả con cháu. Các pstree
lệnh bao gồm tất cả con cháu. Bạn có thể so sánh và đếm đầu ra của hai lệnh này (một cách dễ dàng đang sử dụng | wc
) để xác minh.
kthreadd
luôn luôn là PID 2?