Ответов (14)14
Если кому-то это нужно на C, вы можете использовать readproc.h и libproc:
#include <proc/readproc.h>
#include <proc/sysinfo.h>
float
pid_age(pid_t pid)
{
proc_t proc_info;
int seconds_since_boot = uptime(0,0);
if (!get_proc_stats(pid, &proc_info)) {
return 0.0;
}
// readproc.h comment lies about what proc_t.start_time is. It's
// actually expressed in Hertz ticks since boot
int seconds_since_1970 = time(NULL);
int time_of_boot = seconds_since_1970 - seconds_since_boot;
long t = seconds_since_boot - (unsigned long)(proc_info.start_time / Hertz);
int delta = t;
float days = ((float) delta / (float)(60*60*24));
return days;
}
Вы можете использовать bc
для объединения двух команд в ответе моба и узнать, сколько секунд прошло с момента запуска процесса:
echo `date +%s` - `stat -t /proc/<pid> | awk '{print $14}'` | bc
редактировать:
От скуки в ожидании запуска долгих процессов вот что получилось после нескольких минут возни:
#file: sincetime
#!/bin/bash
init=`stat -t /proc/$1 | awk '{print $14}'`
curr=`date +%s`
seconds=`echo $curr - $init| bc`
name=`cat /proc/$1/cmdline`
echo $name $seconds
Если вы поместите это на свой путь и назовете это так: Sincetime
он напечатает командную строку процесса и секунды с момента запуска. Вы также можете указать это на своем пути:
#file: greptime
#!/bin/bash
pidlist=`ps ax | grep -i -E $1 | grep -v grep | awk '{print $1}' | grep -v PID | xargs echo`
for pid in $pidlist; do
sincetime $pid
done
И чем, если вы запустите:
greptime <pattern>
где шаблоны - это строка или расширенное регулярное выражение, он распечатает все процессы, соответствующие этому шаблону, и секунды с момента их запуска. :)
Где-то наткнулся .. думал просто и полезно
Вы можете использовать команду напрямую в crontab,
* * * * * ps -lf | grep "user" | perl -ane '($h,$m,$s) = split /:/,$F
+[13]; kill 9, $F[3] if ($h > 1);'
или мы можем написать его как сценарий оболочки,
#!/bin/sh
# longprockill.sh
ps -lf | grep "user" | perl -ane '($h,$m,$s) = split /:/,$F[13]; kill
+ 9, $F[3] if ($h > 1);'
И назовите это так, crontab,
* * * * * longprockill.sh
Джоди Си и другие указали, что killall -i
это можно использовать, и это нормально, если вы хотите использовать имя процесса для уничтожения. Но если вы хотите убить с теми же параметрами, что и pgrep -f
, вам нужно использовать что-то вроде следующего, используя чистый bash и /proc
файловую систему.
#!/bin/sh
max_age=120 # (seconds)
naughty="$(pgrep -f offlineimap)"
if [[ -n "$naughty" ]]; then # naughty is running
age_in_seconds=$(echo "$(date +%s) - $(stat -c %X /proc/$naughty)" | bc)
if [[ "$age_in_seconds" -ge "$max_age" ]]; then # naughty is too old!
kill -s 9 "$naughty"
fi
fi
Это позволяет вам находить и уничтожать процессы старше max_age
секунд, используя полное имя процесса ; т.е. названный процесс /usr/bin/python2 offlineimap
может быть остановлен ссылкой на «offlineimap», тогда как killall
представленные здесь решения будут работать только со строкой «python2».
Для всего, что старше одного дня,
ps aux
даст вам ответ, но он упадет до дневной точности, что может быть не так полезно.
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 7200 308 ? Ss Jun22 0:02 init [5]
root 2 0.0 0.0 0 0 ? S Jun22 0:02 [migration/0]
root 3 0.0 0.0 0 0 ? SN Jun22 0:18 [ksoftirqd/0]
root 4 0.0 0.0 0 0 ? S Jun22 0:00 [watchdog/0]
Если вы используете Linux или другую систему с файловой системой / proc, в этом примере вы можете видеть только, что процесс 1 запущен с 22 июня, но не указывает время его запуска.
stat /proc/<pid>
даст вам более точный ответ. Например, вот точная отметка времени для процесса 1, который ps показывает только как Jun22:
ohm ~$ stat /proc/1
File: `/proc/1'
Size: 0 Blocks: 0 IO Block: 4096 directory
Device: 3h/3d Inode: 65538 Links: 5
Access: (0555/dr-xr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2008-06-22 15:37:44.347627750 -0700
Modify: 2008-06-22 15:37:44.347627750 -0700
Change: 2008-06-22 15:37:44.347627750 -0700
Нашел ответ, который мне подходит:
предупреждение: это найдет и убьет долго работающие процессы
ps -eo uid,pid,etime | egrep '^ *user-id' | egrep ' ([0-9]+-)?([0-9]{2}:?){3}' | awk '{print $2}' | xargs -I{} kill {}
(Где user-id - это идентификатор конкретного пользователя с длительными процессами.)
Второе регулярное выражение соответствует времени, которое имеет необязательное число дней, за которым следуют час, минута и второй компонент, поэтому его длина составляет не менее одного часа.
Perl Proc :: ProcessTable сделает свое дело: http://search.cpan.org/dist/Proc-ProcessTable/
Вы можете установить его в debian или ubuntu с помощью sudo apt-get install libproc-processtable-perl
Вот однострочный:
perl -MProc::ProcessTable -Mstrict -w -e 'my $anHourAgo = time-60*60; my $t = new Proc::ProcessTable;foreach my $p ( @{$t->table} ) { if ($p->start() < $anHourAgo) { print $p->pid, "\n" } }'
Или, в более точном формате, поместите это в файл с именем process.pl:
#!/usr/bin/perl -w
use strict;
use Proc::ProcessTable;
my $anHourAgo = time-60*60;
my $t = new Proc::ProcessTable;
foreach my $p ( @{$t->table} ) {
if ($p->start() < $anHourAgo) {
print $p->pid, "\n";
}
}
затем беги perl process.pl
Это дает вам большую гибкость и разрешение в 1 секунду при запуске.