Dynamicznie przycinaj szerokość linii stdout w Bash

9

Ostatnio eksperymentowałem z pspoleceniem i czasami długie ścieżki zawijają się do następnej linii (lub dwóch) i utrudniają czytanie. Chcę przesłać dane pswyjściowe do innego programu, aby ograniczyć wynik do xliczby znaków.

Oto, co do tej pory mam, ale to nie działa całkiem dobrze:

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

$(stty size | cut -d' ' -f2)ocenia się na 167, ale nie wydaje się być poprawnym danymi wejściowymi dla cut.

Czy istnieje sposób, aby ten typ składni działał w trybie bash?

soczewica
źródło
To praca dla mnie. Czy możesz podać jakieś dane wyjściowe?
cuonglm
gdzie jest część dynamiczna? Chcesz mieć inną długość dla określonych warunków? Wygląda na to, że chcesz ograniczyć wszystkie dane wyjściowe do jednej maksymalnej długości
@awk_FTW W zależności od sytuacji mam różne ustawienia okna. Na pełnym ekranie moja szerokość wynosi 167. Ale w innych rozmiarach będę musiał być mniejszy. Dlatego chcę zadzwonić do ssty, aby uzyskać rozmiar.
soczewica
Spróbujtput rmam; ps aux
Stéphane Chazelas
Niektóre powłoki jak zsh, ksh93lub bashprzechowywać w terminalu szerokość$COLUMNS
Stephane Chazelas

Odpowiedzi:

5

Następujące prace:

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

Działa to również:

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

Wydaje się, że problem polega na tym stty, że tty musi mieć standardowe wejście, aby działać. Powyższe dwa podejścia rozwiązują ten problem.

Jest jeszcze inna opcja. Podczas gdy sttystdin i stdout są przekierowywane w powyższych poleceniach, jego stderr nie jest: nadal wskazuje terminal. O dziwo, sttyzadziała również, jeśli jako dane wejściowe podano stderr:

ps aux | cut -c1-$(stty size <&2 | cut -d' ' -f2)
John1024
źródło
Rzeczywiście tak! Właśnie tego szukałem. Ciekawe, dlaczego dodałeś koszulkę na końcu?
soczewica
@lentils Ups, teezostał dodany podczas debugowania. Teraz już go nie ma.
John1024
Do czego odnosi się <& 2? Nigdy wcześniej nie widziałem tego zapisu.
soczewica
@ soczewica W powłoce pliki są ponumerowane. Zero odnosi się do standardowego wejścia, jeden do standardowego wyjścia, a dwa do standardowego błędu. Wyrażenie <&2oznacza uzyskanie danych wejściowych ze standardowego błędu.
John1024
1
sttypobiera ustawienia terminalu na swoim standardzie (robisz to na przykład, stty < /dev/other-ttyaby uzyskać ustawienia innego terminalu). Więc nie jest dziwne, że to nie zadziała, jeśli jego stdin jest fajką lub <&2działa.
Stéphane Chazelas
8

Niektóre muszle podoba zsh, bashlub mkshautomatycznie ustawić $COLUMNSzmienną szerokość terminala, więc nie trzeba powoływać się sttytutaj.

Wszystkie implementacje, psktóre wypróbowałem, obsługują tę niestandardową składnię (typ BSD), same sprawdzając szerokość terminala. Jestem zaskoczony, że twoje nie. Oczekuję jednak, że spojrzy na zawartość zmiennej COLUMNS środowiskowej .

Więc możesz zrobić:

export COLUMNS; ps aux

Jeśli nie,

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

Możesz także powiedzieć terminalowi, aby nie zawijał linii:

tput rmam
ps aux
Stéphane Chazelas
źródło
4

Możesz także pslepiej obsługiwać dane wyjściowe.

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

ps -ww ${opts} #no word wrap

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

Dzięki temu psw razie potrzeby zostanie przetworzone dane wyjściowe zgodnie ze specyfikacjami.

Oczywiście, jeśli nie zawijasz słów, masz problem z brakującymi informacjami. Czy naprawdę potrzebujesz tego wszystkiego do wszystkich procesów? Otwórz go w pager, jeśli tak:

ps ww ${opts} | $PAGER

Jeśli nie, określ, co chcesz zobaczyć:

ps -o args= -p $pid

Alternatywnie możesz wyraźnie poinformować pso swoim terminalu --width:

man ps

...

w Szeroka wydajność. Użyj tej opcji dwa razy, aby uzyskać nieograniczoną szerokość.

-w Szeroka wydajność. Użyj tej opcji dwa razy, aby uzyskać nieograniczoną szerokość.

--width n Ustaw szerokość ekranu.

--widthRzecz działa dokładnie w wybranym specyfikacji bez konieczności pociąga za sobą żadnych dodatkowych filtrów lub procesów pomocniczych (który będzie prawdopodobnie tylko zaśmiecać -auxwyjście nawet więcej). I $COLUMNSjak pokazano powyżej i jak wskazuje Stephane, będzie nawet działać dynamicznie.

Warto jednak zauważyć, że często ludzie próbują dodawać tego rodzaju niepotrzebne filtry, aby umożliwić im przejście |pipeprzez inny filtr w celu przeanalizowania wyników, co również może być niepotrzebne. Oczywiście przez ludzi mam na myśli przede wszystkim siebie.

Argument -output, o którym wspomniałem powyżej, umożliwia filtrowanie pswyświetlanych kolumn , a po dodaniu =przypisania można nawet nazwać kolumnę według własnego uznania. Zostawiam zadanie puste i -ppodaję docelowy proces , $pidwięc jedynym wyjściem psjest $pidnazwa polecenia i jego argswywołanie. I -oledwo rysuje, jak można określić, co psbędzie wyświetlane, a czego nie. Oto kierunek, który poleciłbym ci wziąć, szczególnie poprzez:

man ps

... 

Aby zobaczyć każdy proces w systemie przy użyciu składni BSD:

ps ax

ps axu

Aby wydrukować drzewo procesów:

ps -ejH

ps axjf

Aby uzyskać informacje o wątkach:

ps -eLf

ps axms

Aby uzyskać informacje o bezpieczeństwie:

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

ps axZ

ps -eM

Aby zobaczyć każdy proces działający jako root (rzeczywisty i efektywny identyfikator) w formacie użytkownika:

ps -U root -u root u

Aby zobaczyć każdy proces w formacie zdefiniowanym przez użytkownika:

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

Wydrukuj tylko identyfikatory procesów syslogd:

ps -C syslogd -o pid=

Wydrukuj tylko nazwę PID 42:

ps -p 42 -o comm=

mikeserv
źródło