Bagaimana mencegah "ps" melaporkan prosesnya sendiri?

52
$ ps | grep django
28006 ttys004    0:01.12 /usr/bin/python bin/django celeryd --beat
51393 ttys005    0:01.45 /usr/bin/python bin/django celeryd -l INFO
51472 ttys005    0:01.29 /usr/bin/python bin/django celeryd -l INFO
51510 ttys005    0:01.89 /usr/bin/python bin/django celeryd -l INFO
51801 ttys005    0:01.83 /usr/bin/python bin/django celeryd -l INFO
53470 ttys005    0:03.97 /usr/bin/python bin/django celeryd -l INFO
53780 ttys005    0:00.00 grep django

Apakah ada cara untuk mencegah proses terakhir (yaitu, grep yang dimulai bersamaan dengan perintah ps saya) dilaporkan?

(Saya mulai mencoba membuat regex yang cocok dengan literal tetapi tidak cocok dengan dirinya sendiri, tapi itu sepertinya, um, bukan pendekatan yang tepat ...)

Steve Bennett
sumber

Jawaban:

14

Jawaban saya adalah variasi pada jawaban khas untuk mencari "foobar" di psdaftar. Argumen "-A" "ps"lebih portabel daripada "aux", saya percaya, 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 kurung kurawal dan kemudian menyatukannya kembali. Ketika skrip di shell lebih mudah untuk tetap [^]]di depan pola yang Anda cari untuk dicari. 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 psgrepperintah portabel sebagai berikut. Di sini, saya membuat beberapa perbedaan antara Linux, OS X BSD, dan lainnya. Ini menambahkan header kolom dari ps, memberikan lebih banyak kustompsformat yang sesuai dengan kebutuhan saya, dan menampilkan daftar proses ekstra, ekstra lebar sehingga tidak ada argumen baris perintah yang terlewatkan. Yah, sebagian besar tidak ketinggalan. Java menjadi Java, sering kali melakukan hal-hal dengan cara terburuk yang mungkin, 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 command-lone yang diizinkan untuk memulai suatu proses jauh lebih lama, tetapi tabel proses kernel tidak repot untuk melacak apa pun yang panjangnya lebih dari 1K. Setelah perintah dimulai, nama-perintah dan daftar argumen tidak diperlukan, jadi apa yang disimpan dalam tabel proses hanyalah informasi.

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
Kerugiannya adalah ini akan benar-benar cocok dengan satu karakter lebih (di depan) daripada pola aslinya. Sebagai contoh, ini tidak akan pernah cocok dengan PID. Dan bisa sedikit menyesatkan saat digunakan bersama grep --colour.
Tonin
67

+1 untuk @jamzed jawaban singkat, namun OP mungkin perlu penjelasan:

ps | grep "[d]jango"

Menggunakan regex itu, Anda meluncurkan proses yang string psnya tidak akan cocok dengan dirinya sendiri, karena regexp cocok "django"dan tidak "[d]jango". Dengan begitu Anda akan mengecualikan proses yang memiliki string "[d] jango" yang dalam hal ini adalah grep; Hal yang sama dapat diterapkan ke pgrep, egrep, awk, sed, dll ... perintah mana pun yang Anda gunakan untuk mendefinisikan regex.

Dari man 7 regex

   A bracket expression is a list of characters enclosed in "[]".  It nor‐
   mally matches any single character from the list (but see  below).   If
   the  list  begins  with  '^',  it matches any single character (but see
   below) not from the rest of the list.  If two characters  in  the  list
   are  separated  by '-', this is shorthand for the full range of charac‐
   ters between those two (inclusive) in the collating sequence, for exam‐
   ple,  "[0-9]" in ASCII matches any decimal digit.  It is illegal(!) for
   two ranges to share an endpoint, for example, "a-c-e".  Ranges are very
   collating-sequence-dependent,  and portable programs should avoid rely‐
   ing on them.
hmontoliu
sumber
2
Keren. Saya sebenarnya cukup nyaman dengan regex tetapi tidak bisa segera memikirkan cara untuk mencegah pencocokan regexp itu sendiri. Melampirkan surat dalam tanda kurung siku sangat masuk akal. (Termasuk sesuatu seperti [^!] Juga akan bekerja ...)
Steve Bennett
1
Itu bagus dan licik.
ash
Untuk kasus spesifik 'ps', saya menggunakan '[]' di bagian depan nama proses yang saya cari. Maka saya tidak perlu menguraikan nama proses khusus untuk regex, tetapi masih cocok.
Neromancer
@hmontoliu Tidak bekerja misalnya: ps aux | grep [s]cript1. Bisakah Anda membantu mengomentari solusinya?
SOUser
@hmontoliu Salahku. Tampaknya garis ditampilkan karena pencarian sebelumnya ...
SOUser
30

ps | grep [d]jango

ps | grep d[j]ango

...

ps | grep djang[o]

macet
sumber
Menambahkan spasi jika Anda perlu untuk grep satu char:ps aux| grep "[Z] "
AD
@jamzed Tidak berfungsi misalnya: ps aux | grep [s]cript1atau ps aux | grep [s]cript2. Baris grep masih ditampilkan. Bisakah Anda membantu mengomentari solusinya?
SOUser
@jamzed salahku. Tampaknya garis ditampilkan karena pencarian sebelumnya ...
SOUser
18

Gunakan pgrep sebagai gantinya: pgrep -lf django

ramruma
sumber
Seperti biasa saya lupa menyebutkan platform (OS X dalam hal ini). Agaknya pgrep bekerja di berbagai linux.
Steve Bennett
Saya tidak setuju, @ramruma. Saya datang ke utas ini justru karena pgrepmemberi saya persis masalah ini. Tapi saya harus mengatakan saya sedang mengujinya di CygWin (di mana pstidak dapat menunjukkan baris perintah penuh dari proses).
Sopalajo de Arrierez
Manual menyatakan "Proses pgrep atau pkill yang sedang berjalan tidak akan pernah melaporkan dirinya sebagai kecocokan.", Dan memang saya belum melihatnya melakukannya.
deltab
Saya baru saja berurusan dengan masalah di mana saya pikir pgrepcocok dengan dirinya sendiri. Ternyata itu cocok dengan nama bashfile skrip tempat saya menjalankannya. Menambahkan -xmemperbaikinya, lalu melakukan pencocokan tepat pada nama perintah.
andynormancx
11

Oh, tunggu, ini berfungsi:

ps | grep django | grep -v grep
Steve Bennett
sumber
7
Hanya jika baris perintah proses tidak termasuk secara sah grep, yang tidak dapat Anda andalkan dalam kasus umum.
CVn
8

ps -d | grep django

dari man ps:

 -d                  Lists information  about  all  processes
                     except session leaders.
bla
sumber
masih menunjukkan grep pada milikku ...
Kevin
Ya, itu bekerja untuk saya di OS X.
Steve Bennett
Tidak bekerja dengan baik di Linux.
Acumenus
Secara umum, opsi untuk psnon-portable ini terkenal, jadi tanpa informasi tentang platform ini, jawaban ini tidak terlalu membantu. Lebih jauh lagi, ini jelas tidak memadai ketika Anda tidak yakin bahwa proses yang Anda cari bukanlah pemimpin proses (yaitu ini dapat membantu jika target Anda adalah daemon, tetapi umumnya tidak sebaliknya).
tripleee
Lucu, di Mac ini sepertinya hanya menunjukkan proses grep dan memfilter yang lainnya.
Christopher Hunter