>--
>Is there a way for the sysadmin to set an account to change
>that user's nice default from zero to some other number?
>My problem is that certain users run CPU intensive background
>jobs and forget to nice them so they don't interfere with
>interactive processes. Every time I come in I find myself
>doing a ps -glxa and then renicing their processes for them.
>I'm tired of doing it and would like to just renice their
>accounts once and for all.
> gregg hanna
I had the same problem here until I stumpled over the following program,
which is now running on all servers and works great. It allows users to
run shorttime jobs at normal nice value but longtime jobs are gradually
reniced up to nice level 19. I did not write the program, I am hoping
that you also can use it
Ruedi
/*
** Nice CPU 'hogs'.
** Runs under SunOS 4.0 (ie. requires kvm routines).
**
*/
#include <stdio.h>
#include <kvm.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/timeb.h>
/* Some defines for debuging
#define DEBUG 1
#define DONT_DO_IT 1
*/
#define SLEEPTIME 120 /* in seconds */
#define WHEREIS_RENICE "/usr/etc/renice"
/* When process cpu usage exceeds limit (indexed by priority) then
we increment priority by one */
int limit[19] = { /* Note that all times are in seconds */
3 * 60, 5 * 60, 7 * 60, 12 * 60, 16 * 60,
32 * 60, 64 * 60, 128 * 60, 256 * 60, 512 * 60,
1024 * 60, 2048 * 60, 4096 * 60, 8192 * 60, 16384 * 60,
32768 * 60, 65536 * 60, 131072 * 60, 262144 * 60};
char *pn = "reallynice";
void burychild(); /* This is for burying dead childs */
main()
{
char nice_str[4], pid_str[6];
int cpu_usage, tt;
kvm_t *kd;
struct proc *proc;
struct user *u;
time_t tloc;
/* Make this program daemon */
if(fork())
exit(); /* Make an own process */
if((tt = open("/dev/tty", O_RDWR)) != -1) {
ioctl(tt, TIOCNOTTY, 0); /* Disconnect from tty */
close(tt);
}
/* Set signal SIGCHLD to routine which takes care of zobies by
calling wait */
signal(SIGCHLD, burychild);
/* Open descriptor for Kernel VM routines (begining with kvm_) */
if(!(kd = kvm_open(NULL, NULL, NULL, O_RDONLY, pn)))
exit(1);
while(1) {
/* Rewind the process list, so we could go all process through again */
if(kvm_setproc(kd) == -1) {
kvm_close(kd);
exit(1);
}
/* Get process one by one */
while(proc = kvm_nextproc(kd)) {
/* We aren't inrested system processes (uid under 10),
processes with negative priority or already with the lowest priority */
if(proc->p_uid < 10 || proc->p_nice < 20 || proc->p_nice == 20 + 19)
continue;
/* Get u-area for cpu usage calculations */
if(!(u = kvm_getu(kd, proc)))
continue; /* Read failed for some reason */
/* Calculate cpu usage by adding user time usage to system time usage */
cpu_usage = u->u_ru.ru_utime.tv_sec + u->u_ru.ru_stime.tv_sec;
#ifdef DEBUG
printf("pid %d uid %d nice %d cpu usage %d\n",
proc->p_pid, proc->p_uid, proc->p_nice - 20, cpu_usage);
#endif
/* Check if should lower this processes priority by one */
if(cpu_usage < limit[proc->p_nice - 20])
continue; /* Not yet */
/* We caught something, hopefully big fish. Now we renice this process.
Let's put first time and little other information to stderr
then we have more informative output */
time(&tloc);
fprintf(stderr, "%.24s uid %d pid %d cpu usage %d\n",
ctime(&tloc), proc->p_uid, proc->p_pid, cpu_usage);
fflush(stderr);
sprintf(nice_str, "+%d", proc->p_nice - 20 + 1);
sprintf(pid_str, "%d", proc->p_pid);
#if (DEBUG || DONT_DO_IT)
fprintf(stderr, "renice %s %s\n", nice_str, pid_str);
#else
if(!fork())
execl(WHEREIS_RENICE, "renice", nice_str, pid_str, 0);
#endif
}
sleep(SLEEPTIME);
}
/* We shouldn't reach here in any case so this is commented out,
otherwise compiler gives a warning
kvm_close(kd); */
Quote:}
/* This is called whenever child is killed. By calling this we
could prevent leaving any zombies wondering around. */
void burychild()
{
while(wait(0) != -1);
Quote:}
--
ETH Hoenggerberg (HPM G6) Tel. ++41 1 377 33 97
CH-8093 Zuerich/Switzerland Fax ++41 1 371 48 73