Извлечь значение времени работы из вывода команды "w"
Как я могу получить значение up
снизу команда на linux?
# w
01:16:08 up 20:29, 1 user, load average: 0.50, 0.34, 0.30
USER TTY LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 00:57 0.00s 0.11s 0.02s w
# w | grep up
01:16:17 up 20:29, 1 user, load average: 0.42, 0.33, 0.29
3 ответа
Учитывая, что формат времени безотказной работы зависит от того, меньше ли он или больше, чем 24 часа, лучшее, что я могу придумать, - это двойное awk
:
$ w
18:35:23 up 18 days, 9:08, 6 users,...
$ w | awk -F 'user|up ' 'NF > 1 {print $2}' \
| awk -F ',' '{for(i = 1; i < NF; i++) {printf("%s ",$i)}} END{print ""}'
18 days 9:08
В Linux самый простой способ получить время безотказной работы в (дробных) секундах - через 1-е поле /proc/uptime
(увидеть man proc
):
$ cut -d ' ' -f1 /proc/uptime
350735.47
Чтобы отформатировать это число так же, как w
а также uptime
делать, используя awk
:
$ awk '{s=int($1);d=int(s/86400);h=int(s % 86400/3600);m=int(s % 3600 / 60);
printf "%d days, %02d:%02d\n", d, h, m}' /proc/uptime
4 days, 01:25 # 4 days, 1 hour, and 25 minutes
Чтобы ответить на вопрос как задано - разбор выходных w
(или uptime
чей вывод такой же, как w
1-я строка вывода, которая содержит всю интересующую информацию), которая также работает в macOS / BSD, с гранулярностью целых секунд:
perl
решение:
<(uptime)
это замена процесса Bash, которая обеспечивает uptime
в качестве входных данных для perl
Команда - см. снизу.
$ perl -nle 'print for / up +((?:\d+ days?, +)?[^,]+)/' <(uptime)
4 days, 01:25
Это предполагает, что days
самая большая единица, отображаемая каждый.
perl -nle
говорит Perl обрабатывать ввод построчно, не выводя вывод по умолчанию (-n
), автоматически удаляя завершающий символ новой строки из каждой входной строки на входе и автоматически добавляя один на выходе (-l
);-e
говорит Perl обрабатывать следующий аргумент как скрипт (выражение) для обработки.print for /.../
говорит Perl выводить то, что каждая группа захвата(...)
внутри регулярное выражение/.../
захватывает.up +
соответствует буквальномуup
с предшествующим (как минимум) одним пробелом, за которым следуют 1 или более пробелов (+
)(?:\d+ days?, +)?
является невыражающим подвыражением - из-за?:
- что соответствует:- 1 или более цифр (
\d+
) - с последующим пробелом
- с последующим буквальным
day
, за которым может следовать буквальныйs
(s?
) - отставание
?
делает все подвыражение необязательным, учитывая, что часть количества дней может присутствовать или не присутствовать.
- 1 или более цифр (
[^,]+
соответствует 1 или более (+
) последующие символы до, но не включая буквальный,
([^,]
) - этоhh:mm
часть.Общая группа захвата - внешняя
(...)
поэтому захватывает все выражение времени работы - будь то в составеhh:mm
только или перед<n> day/s>
- и печатает это.
<(uptime)
является заменой процесса Bash (<(...)
) что, собственно говоря, даритuptime
выводится как (временный, самоуничтожающийся) файл, которыйperl
можно читать через стандартный ввод.
Примерно так с gnu sed:
$ w |head -n1
02:06:19 up 3:42, 1 user, load average: 0.01, 0.05, 0.13
$ w |sed -r '1 s/.*up *(.*),.*user.*/\1/g;q'
3:42
$ echo "18:35:23 up 18 days, 9:08, 6 users, load average: 0.09, 0.31, 0.41" \
|sed -r '1 s/.*up *(.*),.*user.*/\1/g;q'
18 days, 9:08