Динамически обрезать ширину линии стандартного вывода в Bash

9

В последнее время я экспериментировал с psкомандой, и иногда длинные пути переносятся на следующую (или две) строку и затрудняют чтение. Я хочу передать psвывод в другую программу, чтобы ограничить вывод xколичеством символов.

Вот то, что у меня есть, но оно работает не совсем правильно:

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

$(stty size | cut -d' ' -f2)оценивается до 167, но не похоже на допустимый ввод для cut.

Есть ли способ заставить этот тип синтаксиса работать в Bash?

чечевица
источник
Это работа для меня. Можете ли вы предоставить какой-то вывод?
cuonglm
где динамическая часть? Вы хотите другую длину для определенных условий? Похоже, что вы хотите ограничить весь вывод одной максимальной длиной
@awk_FTW В зависимости от ситуации у меня разные настройки окна. В полноэкранном режиме моя ширина 167. Но при других размерах мне нужно будет меньше. Вот почему я хочу позвонить ssty, чтобы получить размер.
чечевица
Попробуйтеtput rmam; ps aux
Стефан Шазелас
Некоторые оболочки нравится zsh, ksh93или bashхранить терминал в ширину$COLUMNS
Stéphane Chazelas

Ответы:

5

Следующие работы:

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

Это также работает:

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

Проблема, похоже, заключается в том, что для работы sttyнеобходимо иметь tty на стандартном входе. Два вышеупомянутых подхода решают это.

Есть еще один вариант. Хотя sttystdin и stdout оба перенаправлены в приведенных выше командах, его stderr - нет: он по-прежнему указывает на терминал. Как ни странно, sttyтакже будет работать, если в качестве входных данных ему будет предоставлен stderr:

ps aux | cut -c1-$(stty size <&2 | cut -d' ' -f2)
John1024
источник
Действительно, это так! Это было именно то, что я искал. Просто любопытно, почему вы добавили тройку в конце?
чечевица
@lentils К сожалению, teeбыл добавлен, когда я отлаживал. Это ушло сейчас.
John1024
Что означает <& 2? Я никогда не видел эту запись раньше.
чечевица
@lentils В оболочке файлы нумеруются. Ноль относится к стандартному вводу, один к стандартному выводу и два к стандартной ошибке. Выражение <&2означает получить ваш ввод от стандартной ошибки.
John1024
1
sttyполучает настройки терминала, открытого на его стандартном вводе (вы делаете, например, stty < /dev/other-ttyчтобы получить настройки другого терминала). Так что не странно, что он не будет работать, если его стандартный ввод - труба или это <&2работает.
Стефан Шазелас
8

Некоторые оболочки нравится zsh, bashили mkshавтоматически установить $COLUMNSпеременную ширину терминала, так что вам не нужно ссылаться sttyздесь.

Все реализации, которые psя пробовал, которые поддерживают этот нестандартный (BSD-тип) синтаксис, сами запрашивают ширину терминала. Я удивлен, что твой нет. Я ожидаю, что он будет смотреть на содержимое переменной COLUMNS среды, хотя.

Так что вы могли бы сделать:

export COLUMNS; ps aux

Если не,

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

Вы также можете указать терминалу не переносить строки:

tput rmam
ps aux
Стефан Шазелас
источник
4

Вы также можете обрабатывать psвывод немного лучше.

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

ps -ww ${opts} #no word wrap

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

Это скажет вам при psнеобходимости проанализировать его вывод в соответствии с вашими требованиями.

Конечно, если вы не переносите слова, то у вас проблема с отсутствием информации. Вам действительно нужно все это для всех процессов? Откройте его в пейджере, если это так:

ps ww ${opts} | $PAGER

Если нет, укажите, что вы хотите увидеть:

ps -o args= -p $pid

В качестве альтернативы вы можете явно сообщить psо своем терминале --width:

man ps

...

w Широкий выход. Используйте эту опцию дважды для неограниченной ширины.

-w Широкий выход. Используйте эту опцию дважды для неограниченной ширины.

--width n Установите ширину экрана.

Эта --widthвещь работает точно в соответствии с вашими требованиями без необходимости использования каких-либо дополнительных фильтров или вспомогательных процессов (которые, скорее всего, будут только загромождать ваши -auxрезультаты). И, $COLUMNSкак показано выше, и, как указывает Стефан, он будет работать даже динамически.

Это, вероятно , стоит отметить, однако, что я считаю , люди часто пытаются добавить эти виды ненужных фильтров , чтобы они могли вместить |pipeчерез другой фильтр для разбора вывода , который также очень вероятно, будет излишним. Конечно, под людьми я в основном имею в виду меня.

-oUtput операнда я упомянул выше позволяю фильтровать столбцы , которые psотображаются, а при добавлении =распайки вы можете даже назвать колонки , как вам угодно. Я оставляю назначение пустым и -pпередаю его целевому процессу, $pidтак что единственным выходом psявляется $pidимя команды и ее argsпри вызове. И -oедва царапает поверхность того, как вы можете определить, что psбудет или не будет отображаться. Это направление, которое я бы порекомендовал вам выбрать, особенно через:

man ps

... 

Чтобы увидеть каждый процесс в системе, использующий синтаксис BSD:

ps ax

ps axu

Чтобы распечатать дерево процессов:

ps -ejH

ps axjf

Чтобы получить информацию о темах:

ps -eLf

ps axms

Чтобы получить информацию о безопасности:

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

ps axZ

ps -eM

Чтобы увидеть каждый процесс, выполняющийся от имени пользователя root (реальный и эффективный идентификатор) в формате пользователя:

ps -U root -u root u

Чтобы увидеть каждый процесс в определенном пользователем формате:

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

Выведите только идентификаторы процессов syslogd:

ps -C syslogd -o pid=

Напечатайте только название PID 42:

ps -p 42 -o comm=

mikeserv
источник