Làm cách nào tôi có thể ngăn 'grep' hiển thị trong kết quả ps?


304

Khi tôi tìm kiếm một quá trình không tồn tại, vd

$ ps aux | grep fnord                          
wayne    15745  0.0  0.0  13580   928 pts/6    S+   03:58   0:00 grep fnord

Rõ ràng tôi không quan tâm đến grep - điều đó có ý nghĩa nhiều như tìm kiếm psquy trình!

Làm thế nào tôi có thể ngăn grep hiển thị trong kết quả?


28
Nếu bạn chỉ cần PID của một quá trình, bạn có thể thay thế ps aux |grepbằng pgrep(hoặc pgrep -f).
jofel

6
Câu hỏi tương tự trên ServerfaultSuperuser .
Thor

đầu ra đó có hợp pháp không? có vẻ như không có chương trình nào tên là fnord đang chạy ...
acolyte

4
@acolyte, chính xác là như vậy - nhưng vì nó đang chuyển đầu ra thành grep, grep đang chạy (chờ đầu ra của ps aux, tôi mong đợi). Vì vậy, câu hỏi là làm thế nào để ngăn chặn grep fnordhiển thị dưới dạng một quy trình đang chạy bởi vì rõ ràng tôi không quan tâm đến quy trình đó .
Wayne Werner

2
@acolyte Không có gì ngạc nhiên khi bạn không thể thấy dòng "fnord". Bạn không cần phải có thể nhìn thấy nó. Nếu bạn có khoảng 2 hoặc 3 phút rảnh rỗi, hãy tìm kiếm nó.
Francesco

Câu trả lời:


439

Hóa ra có một giải pháp được tìm thấy trong móc khóa .

$ ps aux | grep "[f]nord"

Bằng cách đặt dấu ngoặc quanh chữ cái và dấu ngoặc kép quanh chuỗi bạn tìm kiếm biểu thức chính, có nội dung: "Tìm ký tự 'f' theo sau là 'nord'."

Nhưng vì bạn đặt dấu ngoặc trong mẫu 'f' hiện được theo sau bởi ']', nên grepsẽ không hiển thị trong danh sách kết quả. Neato!


26
@acolyte: Đầu ra từ ps sẽ bao gồm một dòng kết thúc bằng grep [f]nord. Tuy nhiên, dòng đó sẽ không thực hiện thông qua bộ lọc grep, vì chuỗi [f]nordkhông khớp với biểu thức thông thường [f]nord.
LarsH

9
@LarsH thú vị, cảm ơn! tôi đã đề nghị ps aux | grep fnord | grep -v grep... có vẻ như đã được đề xuất bởi một vài người ... lol
acolyte

5
@progo Vâng, bạn cần phải trích dẫn [ngay cả trong bash. Hãy thử nó với một tập tin được gọi fnordtrong thư mục hiện tại.
Gilles

25
Cắt xén đầu ra pscó thể là một mánh khóe cũ, nhưng nó không đáng tin cậy. Sử dụngpgrep nếu có sẵn.
Gilles

8
@naxa Hãy tưởng tượng bạn có một cuộc gọi chương trình fnordvà một chương trình được gọi safnorde. Hoặc có một người dùng được gọi bfnordvà cuối cùng bạn sẽ giết tất cả các quy trình của anh ta. V.v.
Gilles

164

Một tùy chọn khác mà tôi sử dụng (đặc biệt là chỉ để xem nếu một tiến trình đang chạy) là pgrep lệnh. Điều này sẽ tìm kiếm một quy trình phù hợp, nhưng không liệt kê một dòng grep cho tìm kiếm. Tôi thích nó bởi vì nó là một cách tìm kiếm nhanh chóng, mà không cần regex hay thoát bất cứ điều gì.

pgrep fnord

8
Họ sẽ muốn -ftùy chọn được nhiều hơn như thế ps | grep.
jordanm

@jordanm Thật ra, pgrep -fsẽ giống hơn ps -f | grep.
michelpm

5
Ngoài ra còn có -lđối số để làm cho nó hiển thị lệnh được khớp.
Patrick

15
ps | grep '[f]nord'là thông minh và đáng kính, nhưng pgrep là đúng .
kojiro

3
Bạn luôn có thể làm ps $(pgrep cmd) ...nếu `pgrep thiếu các tùy chọn (mặc dù nó sẽ không hoạt động đối với tập lệnh trống).
Maciej Piechotka

62

Giải pháp lý tưởng là giải pháp do BriGuy trình bày

pgrep fnord 

Nhưng nếu bạn không muốn làm điều đó, bạn chỉ có thể loại trừ tất cả các dòng phù hợp với grep với:

ps aux | grep -v grep | grep "fnord"

7
Nhưng nếu dòng tôi đang tìm kiếm là "bash bash grep bash" thì sao?
Sparr

1
@Sparr Sau đó, bạn nên sử dụng giải pháp tốt nhất: pgrephoặc tìm một giải pháp khác;)
RSFalcon7

Xem ra cho giới hạn chiều dài tên với pgrep. Sử dụng -f để lấy tên đường dẫn đầy đủ hoặc bạn có thể thấy các trận đấu của mình thất bại với tên dài hơn. -l cũng thật tuyệt khi liệt kê các trận đấu
Neil McGill

25

Không phải là giải pháp thanh lịch nhất nhưng bạn có thể làm điều này:

$ ps aux | grep fnord | grep -v grep


Đó là câu trả lời tồi! Bởi vì nếu có một từ greptrong cụm từ của bạn. Nó sẽ không hiển thị quá trình đó. Ví dụ: giả sử một tệp được gọi foo_grep_bar.txtđang được chỉnh sửa bằng nanolệnh. Vì vậy, có một quá trình đang chạy: root 14908 0.0 0.0 110012 1692 pts / 3 S + Oct31 0:00 nano foo_grep_bar.txtTheo câu trả lời này, điều này sẽ không hoạt động: $ ps aux | grep nano | grep -v grepBởi vì có một từ grep trong tên tệp của bạn.
Nabi KAZ

Tôi thích điều này vì nó rõ ràng hơn về ý định của nó hơn là câu trả lời được chấp nhận và hoạt động trong tất cả trừ một trường hợp.
samaspin

1
theo superuser.com/a/409658/450260 bạn nên loại trừ toàn bộ grep fnordkhông chỉ greptức là $ ps aux | grep fnord | grep -v "grep fnord"
Davos

15

Trong zsh grep fnord =(ps aux),.

Ý tưởng là, trước tiên hãy chạy ps aux, đặt kết quả vào một tệp, sau đó sử dụng greptrên tệp đó. Chỉ, chúng tôi không có tệp, vì chúng tôi sử dụng "thay thế quy trình" của zsh.

Để minh họa, hãy thử

ps aux > ps.txt
grep fnord ps.txt
rm ps.txt

Kết quả phải giống nhau.

Nhận xét chung về một số câu trả lời khác. Một số xa đến phức tạp và / hoặc dài để gõ. Đây không chỉ là vấn đề đúng đắn mà còn có thể sử dụng được. Nhưng điều đó không có nghĩa là một số giải pháp đó là xấu; chỉ, chúng phải được bọc trong một giao diện người dùng nhỏ để làm cho chúng có thể sử dụng được.


1
Không biết thay thế quy trình của zsh, nhưng có chắc chắn rằng hai quy trình được gọi lần lượt là quá trình khác và không song song?
Paŭlo Ebermann

3
@ PaŭloEbermann: Đối với song song là <(command). grep grep =(ps aux)không hiển thị bất kỳ dòng nào.
Maciej Piechotka

Zsh cũng có thể match¨ đầu ra từ ps. print -l ${(M)${(f)¨$(ps aux)¨}:#*fnord*}
Friartek

7
ps aux | grep $(echo fnord | sed "s/^\(.\)/[\1]/g")

3
nó trông giống như một IOCCC, nhưng đối với dòng lệnh unix thay vì C ^^ Chỉ | grep $(echo fnord)là không đủ? Bạn cũng yêu cầu sed tìm kiếm và thay thế mỗi char trong "fnord" bằng giá trị riêng của nó? ^^ chúc mừng. Tôi cá là tôi có thể làm lâu hơn nữa, nhưng có lẽ nó sẽ không vui chút nào ^^
Olivier Dulac

1
Tôi xin lỗi vì giọng điệu của bình luận trên của tôi nghe có vẻ khó chịu (và tôi không thể chỉnh sửa nó sau 5 triệu) ... Câu trả lời của bạn thực sự là một niềm vui đọc, và tôi đã không cố làm cho bạn trông tệ. Tôi thực sự nghĩ rằng bạn đã làm nó như thế này trên mục đích ^^
Olivier Dulac

1
Đừng xin lỗi, câu trả lời của bạn thực sự rất thú vị để đọc (và tại chỗ cũng đúng). Ý tôi là pgrep -l $ 1 anyway;)
yPhil

3
@OlivierDulac: Anh ấy không chỉ thay thế char đầu tiên bằng giá trị riêng của nó; ông thay thế nó bằng cách ghép giá trị của nó trong các dấu ngoặc vuông. . +1
LarsH

2
ps aux | grep '[^]]fnord'sẽ tránh thể dục đó.
Stéphane Chazelas

6

Câu trả lời này là GNU cụ thể . Xem câu trả lời của Wayne để có giải pháp tổng quát hơn.

Tìm kiếm các quy trình

Nếu bạn chỉ tìm kiếm các fnordquy trình, bạn có thể sử dụng -Ctùy chọn để chọn theo tên lệnh:

ps -C fnord

Điều này có thể được trộn lẫn với các tùy chọn định dạng kiểu BSD và POSIX theo ý thích của bạn. Xem trang người đàn ông ps để biết danh sách đầy đủ.

Tìm kiếm đôi khi khác?

Nếu bạn cần một cái gì đó cao cấp hơn một tìm kiếm chính xác cho một tên lệnh, đừng mất hy vọng! Điều này vẫn có thể được thực hiện ở psphía bên của đường ống. Tất cả chúng ta phải làm là yêu pscầu loại trừ grepcác quá trình khỏi kết quả:

ps -NC grep | grep 'fnord'

-C grepchọn tất cả các quy trình grep và -Nphủ nhận lựa chọn. Điều này có thể được sử dụng để tìm kiếm các đối số lệnh, một phần của tên lệnh hoặc các biểu thức chính quy phức tạp hơn.


1
Điều này tốt với GNU psnhưng -Ckhông được POSIX chỉ định và có ý nghĩa hoàn toàn khác trên BSD
Eric Renouf

Nó thực sự là một người lập dị không có BSD tương đương (điều đó cũng có nghĩa là nó sẽ không hoạt động trên máy mac). Sử dụng ps -C cho đến nay là câu trả lời đơn giản nhất trong số này.
Christopher Hunter

3

Câu trả lời của tôi là một biến thể của câu trả lời điển hình cho việc tìm kiếm "foobar" trong danh sách 'ps'. Đối số của "-A" "ps" dễ mang theo hơn "phụ", tôi tin, nhưng sự thay đổi này không liên quan đến câu trả lời. Câu trả lời điển hình như thế này:

$ ps -A -ww | grep [f]oobar

Thay vào đó tôi sử dụng mẫu này:

$ ps -A -ww | grep [^]]foobar

Ưu điểm chính là việc viết tập lệnh dựa trên các mẫu này dễ dàng hơn vì bạn chỉ cần nối chuỗi tĩnh "[^]]" với bất kỳ mẫu nào bạn đang tìm kiếm. Bạn không cần phải loại bỏ chữ cái đầu tiên của chuỗi sau đó chèn nó vào giữa các dấu ngoặc vuông và sau đó nối lại chuỗi đó lại với nhau. Khi viết kịch bản trong shell, bạn chỉ cần dán "[^]]" vào trước mẫu mà bạn đang tìm kiếm. Cắt chuỗi trong Bash là một điều xấu xí, vì vậy biến thể của tôi tránh điều đó. Biến thể này cho biết hiển thị các dòng trong đó mẫu khớp với KHÔNG CÓ khung vuông vuông bên phải hàng đầu]. Vì mẫu tìm kiếm để loại trừ một khung vuông thực sự thêm khung vuông vào mẫu nên nó sẽ không bao giờ khớp với chính nó.

Vì vậy, bạn có thể viết một lệnh 'psgrep' di động như sau. Ở đây, tôi thực hiện một số khoản trợ cấp cho sự khác biệt giữa Linux, OS X BSD và các loại khác. Điều này thêm các tiêu đề cột từ 'ps', cung cấp định dạng 'ps' tùy chỉnh hơn phù hợp với các nhu cầu của tôi và hiển thị các quy trình liệt kê thêm, rộng hơn để không bỏ sót đối số dòng lệnh nào. Vâng, hầu hết không được bỏ lỡ. Java là Java, nó thường làm mọi thứ theo cách tồi tệ nhất có thể, do đó, một số dịch vụ java sẽ chạy qua độ dài tối đa được phép của các đối số mà bảng quy trình sẽ theo dõi. Tôi tin rằng đây là 1024 ký tự. Độ dài đơn lệnh được phép bắt đầu một quy trình dài hơn nhiều, nhưng bảng quy trình nhân không bận tâm theo dõi bất cứ thứ gì có độ dài trên 1K. Khi lệnh được bắt đầu, tên lệnh và danh sách đối số là '

psgrep ()
{
    pattern=[^]]${1};
    case "$(uname -s)" in
        Darwin)
            ps -A -ww -o pid,ppid,nice,pri,pcpu,pmem,etime,user,wchan,stat,command | grep -i -e "^[[:space:]]*PID" -e ${pattern}
        ;;
        Linux)
            ps -A -ww -o pid,ppid,tid,nice,pri,pcpu,pmem,etime,user,wchan:20,stat,command | grep -i -e "^[[:space:]]*PID" -e ${pattern}
        ;;
        *)  # other UNIX flavors get a minimalist version.
            ps -A -ww | grep -i -e ${pattern}
        ;;
    esac
}

2

Cách đơn giản nhất để thực hiện việc này sẽ là lưu trữ nó trong một biến trước tiên:

PS_OUTPUT="$(ps aux)"; echo "$PS_OUTPUT" |grep fnord

Gọi ra: grep fnord =(ps aux)Câu trả lời của @ EmanuelBerg là thanh lịch nhất, mặc dù nó đòi hỏi zsh. Tôi đã có một thời gian ngắn trong tập tin RC của mình, nhưng bash phàn nàn về cú pháp đó ngay cả khi có điều kiện ngăn cản đánh giá của nó.


Từ các tệp RC của tôi, tôi có một phiên bản không phân biệt chữ hoa chữ thường có grep's args:

psl() {
  local PS_OUTPUT="$(ps auxww)"
  echo "${PS_OUTPUT%%$'\n'*}" >&2  # title, in stderr to avoid pipes
  echo "${PS_OUTPUT#*$'\n'}" |grep -i "${@:-^}"
}

Mã đi bộ, một viên đạn trên mỗi dòng mã:

  • Nắm bắt psđầu ra dài dòng (trong một localbiến để nó biến mất khi hàm trả về)
  • Hiển thị dòng đầu tiên (tiêu đề) trong lỗi tiêu chuẩn để kết quả có thể được lọc thêm mà không ảnh hưởng đến tiêu đề. Sự thay thế nói: lấy $PS_OUTPUTvà loại bỏ mọi thứ sau nguồn cấp dữ liệu đầu tiên (regex Equiv s/\n.*$//msg:). Điều này ngăn chúng tôi lấy tiêu đề
  • Hiển thị psđầu ra với tất cả mọi thứ trừ dòng đầu tiên (regex Equiv s/^.*\n//m:) và grep nội dung của nó với -itrường hợp không phân biệt chữ hoa chữ thường và với tất cả các đối số đã truyền hàm này (trong trường hợp không có đối số, ^khớp với bắt đầu của bất kỳ dòng nào khớp mọi điều)

1

Có lẽ thời gian để sử dụng một chuỗi thực sự lần này. Việc sử dụng các đường ống làm cho nó song song.

ps aux >f && grep tmpfs <f

Xấu xí vì sẽ có một tệp f, nhưng đó không phải lỗi của tôi khi không có cú pháp cho các quy trình tuần tự mà bạn vẫn muốn sử dụng đầu ra của quy trình đã chạy trước đó.

Đề xuất cú pháp của một toán tử tuần tự:

ps aux ||| grep tmpfs

Sự bất lực của những người bình thường dễ dàng lọc một luồng hầu như không phải là lý do để giới thượng lưu căn cứ vào các chuỗi. Nó sẽ là một bước lùi trong điện toán.
Acumenus

@ABB en.wikipedia.org/wiki/Cransicating_fterential_ Processes có nhiều toán tử hơn các toán tử kết thúc trong trình bao Thompson. Có thể có một toán tử là tuần tự và đã truyền đạt kết quả của nó tới tiến trình tiếp theo trong chuỗi ngay khi thoát ra. Một "bước lùi trong điện toán" bằng cách cung cấp một toán tử bổ sung có vẻ hơi khắc nghiệt.
Anne van Rossum

Liên kết đẹp, nhưng tất nhiên xử lý tuần tự kém hơn trong cả sử dụng CPU và bộ nhớ (hoặc đĩa) - liên quan đến xử lý song song. Trong trường hợp này, nếu trước tiên tôi phải lưu trữ tất cả psđầu ra trước khi tôi grepsử dụng nhiều bộ nhớ (hoặc đĩa) lâu hơn.
Acumenus

0

Lệnh pgrep, như những người khác đã nêu, sẽ trả về PID (ID tiến trình) của các quy trình dựa trên tên và các thuộc tính khác. Ví dụ,

pgrep -d, -u <username> <string>

sẽ cung cấp cho bạn các PID, được phân tách bằng dấu phẩy (,) của tất cả các quy trình có tên trùng khớp được chạy bởi người dùng <username>. Bạn có thể sử dụng công tắc -x trước đó để chỉ trả lại kết quả khớp chính xác.

Nếu bạn muốn có thêm thông tin về các quy trình này (như chạy các tùy chọn phụ trợ từ ps ngụ ý), bạn có thể sử dụng tùy chọn -p với ps, phù hợp dựa trên PID. Ví dụ,

ps up $(pgrep -d, -u <username> <string>)

sẽ cung cấp thông tin chi tiết về tất cả các PID phù hợp với lệnh pgrep.


psthất bại nếu pgreptrả về một tập hợp trống. Tôi có một câu trả lời dựa trên bạn và cố gắng giải quyết vấn đề này.
Acumenus

0

Dưới đây là một ví dụ đơn giản để tìm PID của ssh-agenttên người dùng mà không hiển thị PID của grepchính quá trình:

ps xu | grep "${USER}.*[ ]/usr/bin/ssh-agent" | awk '{print $1 $2;}'

Nếu bạn muốn giết ví dụ ssh-agentcho người dùng hiện tại, bạn có thể sử dụng lệnh sau:

kill `ps xu | grep "${USER}.*[ ]/usr/bin/ssh-agent" | awk '{print $2;}'`

Để tạo một bí danh tiện dụng, hãy thêm vào tệp ~ / .bashrc hoặc ~ / .zshrc của bạn đoạn mã sau:

function function1 () {
    ps xu | grep "$1.*$2" | awk '{print $1" "$2" "$11;}'
}
alias mygrep="function1"

Và để sử dụng bí danh ở đây là những ví dụ để buộc mọi người học các biểu thức chính quy:

. /etc/profile #to make alias usable
mygrep ${USER} ${PROCESS_PATH}
mygrep ${USER} "[f]nord"
mygrep "[f]nord"
mygrep ".*[s]shd"

PS Tôi chỉ thử nghiệm các lệnh này trên Ubuntu và Gentoo.


(1) Câu hỏi không nói rằng người dùng đang tìm kiếm một trong các quy trình của riêng mình - người dùng có thể không biết chủ sở hữu của quy trình mà mình đang tìm kiếm. (2) Giống như câu trả lời này, nó vẫn sẽ thất bại nếu bạn nói "${USER}.* /usr/bin/ssh-agent". Nó hoạt động vì bạn nói [ ]; tức là bạn chỉ đang sử dụng cơ chế của câu trả lời được chấp nhận. Bạn cũng có thể như vậy grep "[s]sh-agent".
G-Man

Bạn đúng rồi. (1) Tôi đã chia sẻ những gì có thể hữu ích khi tôi thấy mình phải đối mặt với trang này một lần (2) Có Tôi đã sử dụng biểu thức chính quy như trong câu trả lời được chấp nhận. (3) Tôi đã cập nhật câu trả lời của mình giống như được chấp nhận vì câu trả lời là tốt hơn, nhưng tôi cũng chỉ ra cách tạo và bí danh được sử dụng với tên người dùng được cung cấp hoặc không có nó. (4) Cũng chỉ ra cách xác định hàm, mặc dù không cần thiết nhưng hoạt động theo cách thú vị vì $ 1 và $ 2 không trùng nhau. Thx # G-Man
Constantin Zagorsky 7/11/2015

-1

Bạn có thể làm điều đó một cách dễ dàng, chỉ với việc xác định ALIAS theo cách của bạn .bashrc như sau:

alias grep='grep -v grep | grep'

Không chắc ai đã bình chọn hay tại sao nhưng điều này cho phép bạn sử dụng toàn bộ ps mà pgrep không sử dụng.
quang

Không chỉ vậy, điều này vô tình loại trừ các quá trình grep khác; nó cũng phá vỡ grepviệc sử dụng trong các trường hợp khác. Hãy thử echo I love grep | grep love.
trosos

@trosos Gần 11 năm tôi đã * nix-ing .. và chưa bao giờ sử dụng mô hình đó bao giờ ... có lẽ vào năm tới - ai biết đúng.
a20

-1

Sử dụng tùy chọn -x (khớp chính xác) làm việc cho tôi. Tôi đã kết hợp nó với -f (dòng lệnh đầy đủ), vì vậy tôi có thể khớp chính xác quy trình của mình với:

pgrep -x -f "path_i_used_when_starting/cmd params_i_used"

Bất cứ ai đang thực hiện việc lái xe xuống bằng cách giải thích? Điều này đã làm việc để giải quyết vấn đề này cho tôi mà không thất bại trong nhiều năm.
psychboom
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.