Potong lebar garis stdout secara dinamis di Bash

9

Akhir-akhir ini, saya telah bereksperimen dengan psperintah, dan terkadang jalur yang panjang membungkus ke baris berikutnya (atau dua) dan membuatnya sulit untuk dibaca. Saya ingin menyalurkan psoutput ke program lain untuk membatasi output ke xjumlah karakter.

Inilah yang saya miliki sejauh ini, tetapi tidak berfungsi dengan benar:

ps aux | cut -c1-$(stty size | cut -d' ' -f2)

$(stty size | cut -d' ' -f2)mengevaluasi ke 167, tetapi tampaknya bukan input yang valid untuk cut.

Apakah ada cara agar sintaks jenis ini bekerja di bash?

kacang-kacangan
sumber
Ini bekerja untuk saya. Bisakah Anda memberikan beberapa hasil?
cuonglm
di mana bagian dinamis? Anda ingin panjang yang berbeda untuk kondisi tertentu? Sepertinya Anda ingin membatasi semua output hingga satu panjang maksimum
@awk_FTW Tergantung situasinya, saya memiliki pengaturan jendela yang berbeda. Pada layar penuh, lebar saya adalah 167. Tetapi pada ukuran lain, saya harus lebih kecil. Itu sebabnya saya ingin memanggil ssty untuk mendapatkan ukuran.
lentil
Cobatput rmam; ps aux
Stéphane Chazelas
Beberapa kerang suka zsh, ksh93atau bashmenyimpan lebar terminal di$COLUMNS
Stéphane Chazelas

Jawaban:

5

Karya-karya berikut:

ps aux | cut -c1-$(stty size </dev/tty | cut -d' ' -f2)

Ini juga berfungsi:

v=$(stty size | cut -d' ' -f2) ; ps aux | cut -c1-$v

Masalahnya adalah bahwa sttyperlu memiliki tty pada input standar untuk berfungsi. Dua pendekatan di atas menyelesaikannya.

Masih ada opsi lain. Sementara sttystdin dan stdout keduanya diarahkan pada perintah di atas, stderrnya tidak: ia tetap menunjuk ke terminal. Anehnya, sttyini juga akan berfungsi jika diberikan stderr sebagai masukan:

ps aux | cut -c1-$(stty size <&2 | cut -d' ' -f2)
John1024
sumber
Memang benar! Ini persis apa yang saya cari. Hanya ingin tahu, mengapa Anda menambahkan tee di akhir?
lentil
@ lentils Ups, teeditambahkan ketika saya sedang debugging. Itu sudah pergi sekarang.
John1024
Apa yang dimaksud <& 2? Saya belum pernah melihat notasi itu sebelumnya.
lentil
@lentils Dalam shell, file diberi nomor. Nol mengacu pada input standar, satu ke output standar, dan dua ke standard error. Ekspresi <&2berarti mendapatkan input Anda dari kesalahan standar.
John1024
1
sttydapatkan pengaturan terminal dibuka pada stdin-nya (Anda lakukan stty < /dev/other-ttyuntuk mendapatkan pengaturan terminal lain misalnya). Jadi tidak aneh kalau itu tidak akan berfungsi jika stdinnya adalah pipa atau <&2berfungsi.
Stéphane Chazelas
8

Beberapa shell suka zsh, bashatau mkshsecara otomatis mengatur $COLUMNSvariabel ke lebar terminal, jadi Anda tidak perlu meminta di sttysini.

Semua implementasi psI mencoba yang mendukung sintaksis non-standar (tipe BSD) menanyakan lebar terminal sendiri. Saya terkejut Anda tidak. Saya berharap itu akan melihat isi dari variabel COLUMNS lingkungan sekalipun.

Jadi Anda bisa melakukan:

export COLUMNS; ps aux

Jika tidak,

ps aux | cut -c"1-$COLUMNS"

Anda juga dapat memberi tahu terminal Anda untuk tidak membungkus baris:

tput rmam
ps aux
Stéphane Chazelas
sumber
4

Anda juga dapat menangani psoutput sedikit lebih baik.

ps --width ${n:-$COLUMNS} ${opts} #set ps terminal width

ps -ww ${opts} #no word wrap

ps -o ${only_interesting_output} ${opts} #trim output

Itu akan memberitahu psuntuk mem-parsing outputnya ke spesifikasi Anda sebagaimana diperlukan.

Tentu saja, jika Anda tidak membungkus kata, maka Anda memiliki masalah info yang hilang. Apakah Anda benar-benar membutuhkan semua itu untuk semua proses? Buka di pager jika demikian:

ps ww ${opts} | $PAGER

Jika tidak, tentukan apa yang ingin Anda lihat:

ps -o args= -p $pid

Atau Anda dapat secara eksplisit menginformasikan psterminal Anda --width:

man ps

...

w Output luas. Gunakan opsi ini dua kali untuk lebar tanpa batas.

-w Output luas. Gunakan opsi ini dua kali untuk lebar tanpa batas.

--width n Atur lebar layar.

The --widthhal bekerja sama persis dengan spesifikasi Anda diminta tanpa harus melibatkan filter tambahan atau proses tambahan (yang kemungkinan hanya akan mengacaukan Anda -auxoutput yang bahkan lebih). Dan $COLUMNSseperti yang ditunjukkan di atas dan sebagaimana ditunjukkan Stephane, ia bahkan akan bekerja secara dinamis.

Mungkin perlu dicatat, bahwa saya menemukan orang sering mencoba untuk menambahkan jenis filter yang tidak perlu sehingga mereka dapat mengakomodasi |pipemelalui filter lain untuk mengurai output yang juga sangat mungkin tidak perlu. Tentu saja, oleh orang-orang, kebanyakan saya bersungguh-sungguh .

The -output operand saya sebutkan di atas memungkinkan Anda untuk filter yang kolom psdisplay, dan ketika Anda menambahkan =assigment Anda bahkan dapat nama kolom sesukamu. Saya meninggalkan tugas kosong dan menyerahkannya target -process $pidjadi satu-satunya keluaran dari pssekali adalah $pidnama perintah dan yang argsdi doa. Dan -onyaris tidak menggores permukaan bagaimana Anda dapat menentukan apa yang psakan atau tidak akan ditampilkan. Ini adalah arah yang saya sarankan Anda ambil, terutama melalui:

man ps

... 

Untuk melihat setiap proses pada sistem menggunakan sintaks BSD:

ps ax

ps axu

Untuk mencetak pohon proses:

ps -ejH

ps axjf

Untuk mendapatkan info tentang utas:

ps -eLf

ps axms

Untuk mendapatkan info keamanan:

ps -eo euser,ruser,suser,fuser,f,comm,label

ps axZ

ps -eM

Untuk melihat setiap proses berjalan sebagai root (ID nyata & efektif) dalam format pengguna:

ps -U root -u root u

Untuk melihat setiap proses dengan format yang ditentukan pengguna:

ps -eo pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,comm

ps axo stat,euid,ruid,tty,tpgid,sess,pgrp,ppid,pid,pcpu,comm

ps -Ao pid,tt,user,fname,tmout,f,wchan

Cetak hanya ID proses dari syslogd:

ps -C syslogd -o pid=

Cetak hanya nama PID 42:

ps -p 42 -o comm=

mikeserv
sumber