Как проверить, как долго запущен процесс?

243

Я хотел бы избежать этого, запустив процесс из приложения мониторинга.

tshepang
источник

Ответы:

311

В Linux с psfrom procps(-ng)(и в большинстве других систем, так как это указано в POSIX):

ps -o etime= -p "$$" 

Где $$находится PID процесса, который вы хотите проверить. Это вернет истекшее время в формате [[dd-]hh:]mm:ss.

Использование -o etimeговорит, psчто вы просто хотите, чтобы поле истекшего времени, и =в конце этого подавляет заголовок (без, вы получите строку, которая говорит, ELAPSEDа затем время на следующей строке; с, вы получите только одну строку со временем) ,

Или, с более новыми версиями набора инструментов procps-ng (3.3.0 или выше) в Linux или во FreeBSD 9.0 или выше (и, возможно, в других), используйте:

ps -o etimes= -p "$$"

(с добавлением s) для форматирования времени в секундах, что более полезно в сценариях.

В Linux psпрограмма получает это /proc/$$/stat, откуда одно из полей (см. man proc) - время запуска процесса. К сожалению, это указывается как время в jiffies (произвольный счетчик времени, используемый в ядре Linux) с момента загрузки системы. Таким образом, вы должны определить время загрузки системы (с /proc/stat), количество jiffies в секунду в этой системе, а затем выполнить математические расчеты, чтобы получить истекшее время в полезном формате.

Оказывается, нелепо сложно найти значение HZ (т. Е. Джиффы в секунду). Из комментариев sysinfo.cв пакете procps можно A) включить файл заголовка ядра и перекомпилировать, если используется другое ядро, B) использовать sysconf()функцию posix , которая, к сожалению, использует жестко запрограммированное значение, скомпилированное в библиотеку C, или C) спросить ядро, но официального интерфейса для этого нет. Итак, psкод включает в себя ряд кладжей, по которым он определяет правильное значение. Ух ты.

Так что удобно, psчто все это сделает за вас. :)

Как отмечает пользователь @ 336_, в Linux (это не переносимо) вы можете использовать statкоманду, чтобы просмотреть даты доступа, изменения или изменения статуса для каталога /proc/$$(где снова $$интересующий процесс). Все три числа должны быть одинаковыми, поэтому

stat -c%X /proc/$$

даст вам время $$начала процесса , в секундах с начала эпохи. Это все еще не совсем то, что вы хотите, так как вам все еще нужно сделать математику, чтобы вычесть это из текущего времени, чтобы получить истекшее время - я думаю, что-то вроде date +%s --date="now - $( stat -c%X /proc/$$ ) seconds"бы сработало, но это немного неуклюже. Одним из возможных преимуществ является то, что если вы используете вывод в длинном формате, например, -c%xвместо -c%X, вы получите большее разрешение, чем целое число секунд. Но, если вам это нужно, вы, вероятно, должны использовать подход аудита процессов, потому что время выполнения команды stat будет влиять на точность.

mattdm
источник
1
Здравствуй! Это etime=опечатка? Я могу найти только etimeв справочных страницах.
Кент Павар
16
@KentPawar Это не опечатка. Пустой =подавляет заголовок. Попробуйте это без, или попробуйтеps -p $$ -o etime="Silly Header Here"
mattdm
4
ps -p $ (pgrep find) -o etime =
мафроз
1
Приятно. Я предпочитаю etimesсебя, так как тогда она машиночитаема
Асфанд Кази
1
@alexmurray Это просто вызывает sysconf()и, следовательно, дает жестко запрограммированное значение из библиотеки C, как уже было сказано, не так ли?
mattdm
36

Портативный:

% ps -o stime,time $$
STIME     TIME
Jan30 00:00:06

т.е. эта оболочка была запущена 30 января и заняла около 6 секунд процессорного времени.

Могут быть более точные или более понятные, но менее портативные способы получения этой информации. Проверьте документацию вашей psкоманды или вашей procфайловой системы.

Под Linux эта информация живет в /proc/$pid/stat.

awk '{print "CPU time: " $14+$15; print "start time: " $22}' /proc/$$/stat

Процессорное время находится в замешательстве; Я не знаю, как случайно найти значение jiffy из оболочки. Время запуска относительно времени загрузки (находится в /proc/uptime).

жилль
источник
3
Найти значение HZ (т. Е. Jiffies in second) оказывается нелепо сложно! Из комментариев в sysinfo.cпакете procps можно: а) включить файл заголовка ядра (и перекомпилировать, если используется другое ядро, б) использовать функцию posix sysconf (), которая, к сожалению, использует жестко запрограммированное значение, скомпилированное в библиотека c или c) запросить ядро, и для этого нет официального интерфейса. Итак, код включает в себя ряд кладжей, по которым он определяет правильное значение. Ух ты.
Mattdm
1
На psстранице руководства указано, что timeэто «совокупное время процессора». Я думаю, что ищет ОП etime, или «истекшее время с начала процесса». pubs.opengroup.org/onlinepubs/000095399/utilities/ps.html
rinogo
1
В конце концов, это не так «переносимо»: «ps: stime: ключевое слово не найдено» во FreeBSD. Это, по крайней мере, поддерживает etime, хотя.
n.st
18
ps -eo pid,comm,cmd,start,etime | grep -i X

X это название процесса

межи
источник
2
вероятно, следует добавить grep -v grep.
Брайан
ps -o pid,comm,cmd,start,etime -p Xпосмотреть на PID X.
codeforester
13

psпринимает -oпараметр, чтобы указать формат вывода, и один из доступных столбцов etime. Согласно справочной странице:

etime - время, прошедшее с начала процесса, в формате [[dd-] чч:] мм: сс.

Таким образом, вы можете запустить это, чтобы получить PID и истекшее время каждого процесса:

$ ps -eo pid,etime

Если вы хотите, чтобы истекшее время определенного PID (например, 12345), вы можете сделать что-то вроде:

$ ps -eo pid,etime | awk '/^12345/ {print $2}'

( Edit : оказывается, есть более короткий синтаксис для вышеуказанной команды; см . Ответ mattdm )

Михаил Мрозек
источник
5

Не знаете, почему это еще не было предложено: в Linux вы можете stat()использовать каталог / proc / [nnn] для вашего PID.

Это поведение явно предназначено для возврата времени запуска процесса, которое оно может выполнять с высоким разрешением и которое ядро ​​может делать точно без хаков jiffies, поскольку ядро ​​может (очевидно) просто проверять соответствующую информацию. Поля доступа, изменения данных и изменения состояния возвращают время начала процесса.

Лучше всего то, что вы можете использовать stat(1)в оболочке или соответствующую привязку stat(2)из $ favourite_programming_language, так что вам может даже не понадобиться запускать внешний процесс.

Обратите внимание, что это не работает с /usr/compat/linux/procFreeBSD; время доступа / изменения / изменения состояния - это текущее время, а время рождения - эпоха UNIX. Довольно глупо, что поддержки нет, если вы спросите меня.

i336_
источник
Где в выводе stat я вижу информацию? Я вижу только доступ, изменение и изменение.
Чепанг
@Tshepang Обратите внимание, что все эти значения одинаковы, и они являются временем начала процесса. Вы все еще должны сделать математику, но это определенно лучше, чем пытаться выяснить смешные моменты, как отмечено в моем ответе.
Mattdm
Вы называете это так: stat /proc/4480это даст вам даты рождения, изменения, изменения и доступа к процессу. Если вам нужен идентификатор процесса, просто используйте "top"
user890332
2

Если вы можете запустить время и затем выполнить команду, вы получите именно то, что вы ищете. Вы не можете сделать это против уже запущенной команды.

[0]% времени сна 20

сон 20 0.00s пользователь 0.00s система 0% процессор 20.014 всего

Slashdot
источник
Знаете ли вы, как я могу сделать это при мониторинге запущенного процесса, пока он не закончится?
lrkwz
1

Вы можете получить время начала процесса, посмотрев на statфайл статистики, сгенерированный им proc, отформатировав его dateи вычтя из текущего времени:

echo $(( $(date +%s) - $(date -d "$(stat /proc/13494/stat | grep Modify | sed 's/Modify: //')" +%s) ))

где 13494ваш процесс PID

катушки
источник
1

$ ps -eo lstart получить время начала

$ ps -eo etime получить длительность / истекшее время

$ ps -eo pid,lstart,etime | grep 61819
  PID                   STARTED     ELAPSED
  61819 Mon Sep 17 03:01:35 2018    07:52:15

61819 - это идентификатор процесса.

Терри Ван
источник
Использование lstart может быть проблематичным, это перекосы - unix.stackexchange.com/questions/274610/...
ОДС
1

Время в секундах: expr $(date +"%s") - $(stat -c%X /proc/<PID HERE>)

Shardj
источник
Мне кажется, это очень небольшая вариация той, о которой уже упоминал mattdm : date +%s --date="now - $( stat -c%X /proc/$$
Джефф Шаллер
Это не сработало для меня в моем минимальном экземпляре докера Alpine, поэтому я написал этот
Shardj