Bagaimana saya bisa mencegah 'grep' muncul di hasil ps?

304

Ketika saya mencari beberapa proses yang tidak ada, mis

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

Jelas saya tidak peduli tentang grep - itu masuk akal seperti mencari psproses!

Bagaimana saya mencegah grep muncul di hasil?

Wayne Werner
sumber
28
Jika Anda hanya membutuhkan PID suatu proses, Anda dapat menggantinya ps aux |grepdengan pgrep(atau pgrep -f).
jofel
6
Pertanyaan yang sama pada Serverfault dan Superuser .
Thor
apakah output itu sah? tampaknya tidak ada program bernama fnord yang menjalankan ...
acolyte
4
@acolyte, hanya itu - tetapi karena memipis output ke grep, grep sedang berjalan (menunggu output dari ps aux, saya harapkan). Jadi pertanyaannya adalah bagaimana mencegah grep fnordmuncul sebagai proses yang berjalan karena jelas saya tidak tertarik pada yang satu itu.
Wayne Werner
2
@acolyte itu tidak mengherankan bahwa Anda tidak dapat melihat garis "fnord". Anda tidak seharusnya bisa melihatnya. Jika Anda punya waktu 2 atau 3 menit, cari saja.
Francesco

Jawaban:

439

Ternyata ada solusi yang ditemukan di gantungan kunci .

$ ps aux | grep "[f]nord"

Dengan meletakkan tanda kurung di sekitar huruf dan mengutip di sekitar string Anda mencari regex, yang mengatakan, "Temukan karakter 'f' diikuti oleh 'nord'."

Tetapi karena Anda memasukkan tanda kurung ke dalam pola 'f' sekarang diikuti oleh ']', jadi greptidak akan muncul di daftar hasil. Neato!

Wayne Werner
sumber
26
@acolyte: Output dari ps akan menyertakan baris yang diakhiri dengan grep [f]nord. Namun, garis itu tidak akan masuk melalui filter grep, karena string [f]nordtidak cocok dengan ekspresi reguler [f]nord.
LarsH
9
@ LarsH menarik, terima kasih! saya akan menyarankan ps aux | grep fnord | grep -v grep... yang tampaknya telah disarankan oleh beberapa orang ... lol
acolyte
5
@progo Ya, Anda perlu mengutip [genap di bash. Cobalah dengan file yang disebut fnorddi direktori saat ini.
Gilles
25
Menerima keluaran psmungkin merupakan trik lama, tetapi tidak dapat diandalkan. Gunakanpgrep jika tersedia.
Gilles
8
@naxa Bayangkan Anda memiliki panggilan program fnorddan program yang dipanggil safnorde. Atau ada pengguna yang dipanggil bfnord, dan Anda akhirnya membunuh semua prosesnya. Dll
Gilles
164

Opsi lain yang saya gunakan (terutama hanya untuk melihat apakah suatu proses sedang berjalan) adalah pgrep perintah. Ini akan mencari proses pencocokan, tetapi tidak mencantumkan baris grep untuk pencarian. Saya suka karena ini adalah cara pencarian yang cepat, tanpa regexing atau melarikan diri apa pun.

pgrep fnord
BriGuy
sumber
8
Mereka akan menginginkan -fopsi menjadi lebih seperti ps | grep.
jordanm
@jordanm Sebenarnya, pgrep -fakan lebih mirip ps -f | grep.
michelpm
5
Ada juga -largumen untuk membuatnya menunjukkan perintah yang cocok.
Patrick
15
ps | grep '[f]nord'pintar dan terhormat, tetapi pgrep benar .
kojiro
3
Anda selalu dapat melakukannya ps $(pgrep cmd) ...jika `pgrep adalah opsi yang hilang (meskipun tidak akan berfungsi untuk set perintah kosong).
Maciej Piechotka
63

Solusi ideal adalah yang dipresentasikan oleh BriGuy

pgrep fnord 

Tetapi jika Anda tidak ingin melakukan itu, Anda bisa mengecualikan semua baris yang cocok dengan grep dengan:

ps aux | grep -v grep | grep "fnord"
RSFalcon7
sumber
7
tetapi bagaimana jika baris yang saya cari adalah "bash bash grep bash"?
Sparr
1
@Sparr Maka Anda harus menggunakan solusi terbaik: pgrepatau menemukan yang lain;)
RSFalcon7
Perhatikan batas panjang nama dengan pgrep. Gunakan -f untuk mendapatkan nama path lengkap atau Anda mungkin menemukan pasangan Anda gagal dengan nama yang lebih panjang. -Aku juga senang mendaftar pertandingan
Neil McGill
25

Bukan solusi yang paling elegan tetapi Anda bisa melakukan ini:

$ ps aux | grep fnord | grep -v grep

Brandon Kreisel
sumber
Itu jawaban yang buruk! Karena jika ada kata grepdalam frasa Anda. Itu tidak akan menunjukkan proses itu. Sebagai contoh, misalkan file yang dipanggil foo_grep_bar.txtsedang diedit oleh nanoperintah. Jadi ada proses yang berjalan: root 14908 0.0 0.0 110012 1692 pts / 3 S + Oct31 0:00 nano foo_grep_bar.txtMenurut jawaban ini, ini tidak akan berhasil: $ ps aux | grep nano | grep -v grepKarena ada kata grep di nama file Anda.
Nabi KAZ
Saya lebih suka ini sebagai lebih eksplisit tentang niatnya daripada jawaban yang diterima dan bekerja di semua kecuali satu kasus.
samaspin
1
sesuai superuser.com/a/409658/450260 Anda harus mengecualikan penuh grep fnordbukan hanya grepyaitu $ ps aux | grep fnord | grep -v "grep fnord"
Davos
15

Di zsh grep fnord =(ps aux),.

Idenya adalah, pertama-tama jalankan ps aux, masukkan hasilnya dalam file, lalu gunakan greppada file itu. Hanya saja, kami tidak memiliki file, karena kami menggunakan "proses substitusi" zsh.

Sebagai ilustrasi, cobalah

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

Hasilnya harus sama.

Komentar umum tentang beberapa jawaban lain. Beberapa jauh rumit dan / atau panjang untuk diketik. Ini bukan hanya masalah menjadi benar, itu harus dapat digunakan juga. Tetapi itu tidak berarti beberapa dari solusi itu buruk; hanya saja, mereka harus dibungkus dengan mini-UI untuk membuatnya dapat digunakan.

Emanuel Berg
sumber
1
Tidak mengetahui proses substitusi zsh, tetapi apakah pasti bahwa kedua proses tersebut disebut satu demi satu dan tidak secara paralel?
Paŭlo Ebermann
3
@ PaŭloEbermann: Paralel adalah <(command). grep grep =(ps aux)tidak menunjukkan garis apa pun.
Maciej Piechotka
Zsh juga dapat ¨match¨ output dari ps. print -l ${(M)${(f)¨$(ps aux)¨}:#*fnord*}
Friartek
7
ps aux | grep $(echo fnord | sed "s/^\(.\)/[\1]/g")
yPhil
sumber
3
ini terlihat seperti IOCCC, tetapi untuk baris perintah unix alih-alih C ^^ Tidak | grep $(echo fnord)cukup? Anda juga meminta sed untuk mencari dan mengganti masing-masing char di "fnord" dengan nilainya sendiri? ^^ selamat. Saya yakin saya bisa melakukan yang lebih lama lagi, tapi mungkin tidak akan selucu ^^
Olivier Dulac
1
Saya minta maaf karena nada komentar saya di atas mungkin terdengar ofensif (dan saya tidak dapat mengeditnya setelah 5juta) ... Jawaban Anda benar-benar bacaan yang menyenangkan, dan saya tidak berusaha membuat Anda terlihat buruk. Saya pikir Anda sengaja melakukannya seperti ini dengan sengaja ^^
Olivier Dulac
1
Jangan minta maaf, jawaban Anda benar-benar menyenangkan untuk dibaca (dan tepat juga). Maksud saya pgrep -l $ 1;)
yPhil
3
@OlivierDulac: Dia tidak hanya mengganti char pertama dengan nilainya sendiri; ia menggantinya dengan gabungan nilai di antara tanda kurung. (Kurung kotak itu tidak spesial, itu harfiah.) Pada dasarnya, dia menggeneralisasi jawaban Wayne Werner, sehingga proses menempatkan tanda kurung di sekitar karakter pertama dapat dituliskan. +1
LarsH
2
ps aux | grep '[^]]fnord'akan menghindari senam itu.
Stéphane Chazelas
6

Jawaban ini khusus untuk GNU . Lihat jawaban Wayne untuk solusi yang lebih umum.

Mencari proses

Jika Anda hanya mencari fnordproses, Anda dapat menggunakan -Copsi untuk memilih dengan nama perintah:

ps -C fnord

Ini dapat dicampur dengan opsi format gaya BSD dan POSIX sesuai keinginan Anda. Lihat halaman manual ps untuk daftar lengkap.

Mencari yang lain?

Jika Anda membutuhkan sesuatu yang lebih maju daripada pencarian yang tepat untuk nama perintah, jangan kehilangan harapan! Ini masih bisa dilakukan di pssisi pipa. Yang harus kita lakukan adalah memberi tahu psuntuk mengecualikan grepproses dari hasil:

ps -NC grep | grep 'fnord'

-C grepmemilih semua proses grep, dan -Nmeniadakan seleksi. Ini dapat digunakan untuk mencari argumen perintah, bagian dari nama perintah, atau ekspresi reguler yang lebih kompleks.

Morgan
sumber
1
Ini bagus untuk GNU pstetapi -Ctidak ditentukan oleh POSIX dan memiliki arti yang sama sekali berbeda pada BSD
Eric Renouf
Ini benar-benar mengecewakan tidak ada BSD yang setara (yang juga berarti itu tidak akan berfungsi pada mac). Menggunakan ps -C sejauh ini merupakan jawaban paling sederhana dari semua ini.
Christopher Hunter
3

Jawaban saya adalah variasi pada jawaban khas untuk mencari "foobar" di daftar 'ps'. Argumen "-A" "ps" lebih portabel daripada "aux", saya yakin, tetapi perubahan ini tidak relevan dengan jawabannya. Jawaban khasnya terlihat seperti ini:

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

Sebagai gantinya saya menggunakan pola ini:

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

Keuntungan utama adalah bahwa lebih mudah untuk menulis skrip berdasarkan pola ini karena Anda hanya menyatukan string statis "[^]]" dengan pola apa pun yang Anda cari. Anda tidak perlu melepas huruf pertama dari string kemudian memasukkannya di antara kawat kurawal dan kemudian menyatukannya kembali. Saat menulis skrip di shell, lebih mudah untuk hanya menempelkan "[^]]" di depan pola yang sedang Anda cari. Mengiris tali di Bash adalah hal yang jelek, jadi variasi saya menghindari itu. Variasi ini mengatakan perlihatkan garis-garis di mana polanya cocok TANPA tanda kurung siku kanan]. Karena pola pencarian untuk mengecualikan braket persegi sebenarnya menambahkan braket persegi ke pola maka tidak akan pernah cocok dengan dirinya sendiri.

Jadi Anda bisa menulis perintah 'psgrep' portabel sebagai berikut. Di sini, saya membuat beberapa perbedaan antara Linux, OS X BSD, dan lainnya. Ini menambahkan tajuk kolom dari 'ps', memberikan format 'ps' lebih khusus yang sesuai dengan kebutuhan saya, dan menampilkan proses daftar ekstra, ekstra lebar sehingga tidak ada argumen baris perintah terlewatkan. Yah, sebagian besar tidak ketinggalan. Java menjadi Java, sering kali melakukan hal-hal dengan cara yang paling buruk, sehingga Anda beberapa layanan java akan berjalan melewati argumen panjang maksimum yang dibolehkan bahwa tabel proses akan melacak. Saya percaya ini adalah 1024 karakter. Panjang perintah-tunggal yang diizinkan untuk memulai suatu proses jauh lebih lama, tetapi tabel proses kernel tidak repot-repot melacak apa pun yang panjangnya lebih dari 1K. Setelah perintah dimulai, nama-perintah dan daftar argumen tidak

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
}
Noah Spurrier
sumber
2

Cara shell-agnostik yang paling sederhana untuk melakukan ini adalah menyimpannya dalam sebuah variabel terlebih dahulu:

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

Info: @ EmanuelBerg sejauh ini grep fnord =(ps aux)adalah jawaban yang paling elegan, meskipun harus zsh. Saya sempat memilikinya di file rc saya, tetapi bash mengeluh tentang sintaks itu bahkan meskipun kondisional yang harus mencegah evaluasinya.


Dari file rc saya, saya memiliki versi case-insensitive yang mengambil argumen grep:

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

Kode berjalan, satu peluru per baris kode:

  • Tangkap psoutput verbose (dalam localvariabel sehingga hilang ketika fungsi kembali)
  • Tampilkan baris pertama (judul) dalam kesalahan standar sehingga hasilnya dapat disaring lebih lanjut tanpa mempengaruhi judul. Substitusi mengatakan: ambil $PS_OUTPUTdan hapus semuanya setelah umpan baris pertama (regex equiv:) s/\n.*$//msg. Ini mencegah kita dari mengambil judul
  • Tampilkan psoutput dengan segala sesuatu kecuali baris pertama (regex equiv:) s/^.*\n//mdan ambil isinya dengan -icase-insensitive dan dengan semua argumen yang menyerahkan fungsi ini (dalam kasus tidak ada argumen ^,, yang cocok dengan awal dari setiap baris yang cocok dengan segala sesuatu)
Adam Katz
sumber
1

Mungkin waktu untuk menggunakan urutan nyata saat ini. Penggunaan pipa membuatnya paralel.

ps aux >f && grep tmpfs <f

Jelek karena akan ada file f , tetapi bukan salah saya bahwa tidak ada sintaks untuk proses sekuensial di mana Anda masih ingin menggunakan output dari proses yang sebelumnya dijalankan.

Saran untuk sintaksis operator sekuensial:

ps aux ||| grep tmpfs
Anne van Rossum
sumber
Ketidakmampuan masyarakat umum untuk dengan mudah menyaring aliran bukanlah alasan bagi kaum elit untuk mendasarkan diri mereka pada urutan. Ini akan menjadi langkah mundur dalam komputasi.
Acumenus
@ABB en.wikipedia.org/wiki/Communicating_ berikutnyaential_processes memiliki lebih banyak operator daripada yang berakhir di shell Thompson. Mungkin saja ada operator yang berurutan, dan yang mengkomunikasikan hasilnya ke proses selanjutnya dalam urutan segera setelah keluar. "Langkah mundur dalam komputasi" dengan menyediakan operator tambahan tampaknya agak keras.
Anne van Rossum
Tautan yang bagus, tetapi tentu saja pemrosesan sekuensial lebih buruk baik dalam penggunaan CPU dan memori (atau disk) - relatif terhadap pemrosesan paralel. Dalam hal ini, jika saya harus menyimpan semua psoutput terlebih dahulu sebelum saya grep, saya menggunakan lebih banyak memori (atau disk) lebih lama.
Acumenus
0

Perintah pgrep, seperti yang telah dinyatakan orang lain, akan mengembalikan PID (ID proses) proses berdasarkan nama dan atribut lainnya. Sebagai contoh,

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

akan memberi Anda PID, dibatasi oleh koma (,) dari semua proses yang namanya cocok dijalankan oleh pengguna <username>. Anda dapat menggunakan sakelar -x sebelum hanya mengembalikan kecocokan persis.

Jika Anda ingin mendapatkan informasi lebih lanjut tentang proses ini (seperti menjalankan opsi aux dari ps menyiratkan), Anda dapat menggunakan opsi -p dengan ps, yang cocok berdasarkan PID. Jadi, misalnya,

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

akan memberikan informasi terperinci dari semua PID yang cocok dengan perintah pgrep.

eToThePiIPower
sumber
psgagal jika pgrepmengembalikan set kosong. Saya punya jawaban yang dibangun di atas milik Anda dan mencoba mengatasi masalah ini.
Acumenus
0

Berikut adalah contoh sederhana untuk menemukan PID ssh-agentuntuk nama pengguna tanpa menunjukkan PID grepproses itu sendiri:

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

Jika Anda ingin misalnya membunuh ssh-agentuntuk pengguna saat ini, Anda dapat menggunakan perintah berikut:

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

Untuk membuat alias yang berguna tambahkan ke file ~ / .bashrc atau ~ / .zshrc Anda dengan kode berikut:

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

Dan menggunakan alias di sini adalah contoh untuk memaksa semua orang belajar ekspresi reguler:

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

PS Saya hanya menguji perintah ini di Ubuntu dan Gentoo.

Constantin Zagorsky
sumber
(1) Pertanyaannya tidak mengatakan bahwa pengguna sedang mencari salah satu prosesnya sendiri - pengguna mungkin tidak tahu pemilik proses yang ia cari. (2) Seindah jawaban ini, masih akan gagal jika Anda mengatakannya "${USER}.* /usr/bin/ssh-agent". Ini berhasil karena Anda berkata [ ]; yaitu, Anda hanya menggunakan mekanisme jawaban yang diterima. Anda mungkin juga adil grep "[s]sh-agent".
G-Man
Kamu benar. (1) Saya membagikan apa yang mungkin berguna ketika saya menemukan diri saya menghadap halaman ini sesekali (2) Ya saya menggunakan ekspresi reguler seperti pada jawaban yang diterima. (3) Saya memperbarui jawaban saya menjadi sama dengan yang diterima karena lebih baik, tetapi saya juga menunjukkan cara membuat dan alias digunakan dengan nama pengguna yang disediakan atau tanpa itu. (4) Juga diperlihatkan cara mendefinisikan fungsi, meskipun tidak perlu tetapi berfungsi dengan cara yang menarik karena $ 1 dan $ 2 tidak tumpang tindih. Thx # G-Man
Constantin Zagorsky
0

Inilah versi lanjutan dari grep -v grepsolusi, memfilter semua grepproses yang belum berjalan lebih dari satu detik, yang merupakan peningkatan dari "hanya buang semua kejadian grep".

$ ps -ef | grep -vw "00:00:00 grep" | grep <searchTerm>

masing-masing

$ ps aux | grep -vw "0:00 grep" | grep <searchTerm>

Ini mungkin tidak portabel, dan tergantung pada format output aktual lokal Anda ps perintah .

Anda mungkin ingin menggabungkan ini dengan grepoutput berwarna untuk kenyamanan:

$ alias grep='grep --color=auto'
Murphy
sumber
-1

Menggunakan opsi -x (pencocokan persis) bekerja untuk saya. Saya menggabungkannya dengan -f (baris perintah penuh), sehingga saya bisa mencocokkan proses saya dengan:

pgrep -x -f "path_i_used_when_starting/cmd params_i_used"
moodboom
sumber
Akankah siapa pun yang melakukan drive-by downvoting menjelaskan diri mereka sendiri? Ini telah bekerja untuk menyelesaikan masalah ini untuk saya tanpa gagal selama bertahun-tahun.
moodboom
-2

Anda dapat melakukannya dengan mudah, hanya dengan mendefinisikan ALIAS di .bashrc seperti ini:

alias grep='grep -v grep | grep'
Keivan Beigi
sumber
Tidak yakin siapa yang memilih atau mengapa tetapi ini memungkinkan Anda untuk menggunakan penuh ps yang pgrep tidak gunakan.
opticyclic
1
Tidak hanya itu secara tidak sengaja mengecualikan proses grep lainnya; itu juga merusak greppenggunaan dalam kasus lain. Coba echo I love grep | grep love.
trosos
@trosos Hampir 11 tahun saya sudah * nix-ing .. dan belum pernah menggunakan pola itu ... mungkin tahun depan sekalipun - siapa tahu benar.
a20