Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

10.3: Control CPU usage while using fast user switching System
This is a follow-up to an earlier hint regarding fast user switching and scheduling priority/cpu usage. One commenter suggested renicing user processes as part of login or logout script, but I prefer to run the following script as a cron job, for a couple of reasons. First, I can run the cron job as root (which renice requires to increase priority) without having SetUID programs lying around. Second, a periodic cron job catches at & batch jobs, periodic jobs, processes started via ssh, and other processes that are started by other users after logout or login.
B The downside to this approach, of course, is that there is a certain variable lag time between login/user switching and a user's processes being reniced. The truly harried or impatient may want to run the script via sudo on login.

Save the following script someplace logical; I use /usr/sbin/ or /var/root/bin/.

#!/bin/sh
#
# switch_nice
#
# renice processes so that the user at the main login window gets priority
#
 
# Determine who is logged in at the main terminal
#
# The user currently logged on at the main main termainal will be returned
# as the final argument to the only instance of login running on std
TOPUSER=`ps -auxww | grep login | grep std | grep -v grep | awk '{print $13}'`

# Determine what other processes have been given priority by admins
# and ought to be exempt -- THE FOLLOWING SHOULD BE ONE LONG LINE WITH A
# SINGLE SPACE REPLACING THE LINE BREAK!
EXEMPTIONS=(`ps -auxo nice | awk '{print $1, $2, $11}' | grep -v root |
 grep -v nobody | grep -e - | awk '{print $2}'`)

# Get names of users to be reniced -- THE FOLLOWING SHOULD BE ONE LONG
# LINE WITH A SINGLE SPACE REPLACING THE LINE BREAK!
SWITCHEDUSER=(`ps -auxww | grep -v $TOPUSER | grep -v root | grep -v nobody |
 awk '{print $1, $2}' | grep -v USER | awk '{print $1}' | sort -u`)

# Renice: others to 15, main terminal to 0, priority processes to -15
echo ${SWITCHEDUSER[*]} | xargs renice 15 -u
renice 0 -u $TOPUSER
echo ${EXEMPTIONS[*]} | xargs renice -15 -p

# Add additional rules...I renice my seti@home instances to 20
Then chmod u+x and add the following to your /etc/crontab:
*/5   *     *     *     *     root    </path/to/switch_nice>
Now every five minutes the system will check for processes run by other users and renice them.
    •    
  • Currently 2.17 / 5
  You rated: 1 / 5 (6 votes cast)
 
[11,657 views]  

10.3: Control CPU usage while using fast user switching | 6 comments | Create New Account
Click here to return to the '10.3: Control CPU usage while using fast user switching' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
10.3: Control CPU usage while using fast user switching
Authored by: stetner on Jan 21, '04 05:18:10PM

You need to be careful. When I execute your

SWITCHEDUSER=

line I get

mysql
postfix
www

Now those are not users whose processes I (or you most likely) want to slow down.

I always worry about indiscriminately messing with other processes. If you understand what is occurring that is OK, if you do not, then you may be buying yourself a lot of grief.



[ Reply to This | # ]
10.3: Control CPU usage while using fast user switching
Authored by: Han Solo on Jan 21, '04 10:56:58PM
The previous commenter's caveat is a good one. While I do not pretend to know enough Unix to pull this off, it seems that in principle one could use ps to identify a list of users with UID > 500 -- which I believe should only include "real live" users -- then exclude the current user from that list and renicing all processes with UIDs on that list down to 15.

It would be nice to be able to execute scripts upon "account activation" -- whether that be a login or an account switch via FUS. Ideas anyone?

[ Reply to This | # ]

10.3: Control CPU usage while using fast user switching
Authored by: LightYear on Jan 27, '04 03:02:42AM

Starting scripts at login:
http://www.macosxhints.com/article.php?story=20030116061349986&query=loginhook

Can anyone confirm this works as expected with FUS?

---
* Nothing is foolproof to a sufficiently talented fool *



[ Reply to This | # ]
10.3: Control CPU usage while using fast user switching
Authored by: jen729w on Mar 12, '05 12:20:13AM
Unix people will doubtless have worked this out already, but I post this here for "part-time fiddlers" such as myself who may need a pointer.

As the comment below notes, the SWITCHEDUSER variable can contain the names of system accounts such as www. This is undesirable. It's easy enough to modify the script to exclude these usernames, however:

  1. Copy the TOPUSER=`ps -auxww | grep login | grep std | grep -v grep | awk '{print $13}'` line from the script into a Terminal window and hit return. Nothing much will happen.
  2. Copy the SWITCHEDUSER=(`ps -auxww | grep -v $TOPUSER | grep -v root | grep -v nobody | awk '{print $1, $2}' | grep -v USER | awk '{print $1}' | sort -u`) line into a Terminal window and hit return. (Make sure it's all on one line - you may have to copy 'n paste twice without hitting return in the middle.) Again, nothing much happens.
  3. Type set in Terminal. You'll be shown a list of variables - look for the SWITCHEDUSER line. Mine looks like this:
    SWITCHEDUSER=([0]="will" [1]="www").
  4. In this case, will is my flatmate, whose processes I want to renice. www is the system service, which I want to leave alone.
  5. In the script, edit the SWITCHEDUSER line, adding a grep -v [system-account-name] | statement for each system account. Add the statement immediately after the grep -v nobody | statement. My script therefore now contains the following line:
    SWITCHEDUSER=(`ps -auxww | grep -v $TOPUSER | grep -v root | grep -v nobody | grep -v www | awk '{print $1, $2}' | grep -v USER | awk '{print $1}' | sort -u`)
    ...but yours may contain more entries depending on what was contained in SWITCHEDUSER.
  6. All done. Go and put the kettle on.

This still isn't perfect - any new services which are installed in the future won't be reniced. It's up to you to remember and add their account names to the script.

I hope that all makes sense (and that it helps someone, somewhere). :-)

j.

[ Reply to This | # ]

10.3: Control CPU usage while using fast user switching
Authored by: mlibbey on Jun 03, '07 05:22:23PM
in 10.4, when I run the printed TOPUSER line (as me or root), I get no results. As root,
TOPUSER=`id -p | grep login | awk '{print $2}'`
does return me. (when running that line as me, I'd have to change the login to uid:
TOPUSER=`id -p | grep uid | awk '{print $2}'`

[ Reply to This | # ]
10.3: Control CPU usage while using fast user switching
Authored by: mlibbey on Jun 09, '07 03:34:59PM
I rewrote this a bit so that it works in 10.4 (well, at least the posted one didn't work for me)

#!/bin/sh
#
# switch_nice
#
# renice processes so that the user at the main login window gets priority

#optimization, only do the renice if the user has changed. Store that in /tmp
olduser=`cat /tmp/user`;

# Determine who is logged in at the main terminal
#
# The user currently logged on at the main main terminal will be returned
# as the final argument to the only instance of login running on std

x=`last -1| awk '{print $1}'`
TOPUSER=`ls -1 /Users/ | grep $x`

if (test $olduser != $TOPUSER); then
# the user has changed, so proceed
#change the user file so that olduser will get updated next time
echo "$TOPUSER" > /tmp/user;

# I like a bit of logging -- uncomment these if in the crontab you do 
#<path/to/switchnice >> /var/log
#date
#echo "new user, now $TOPUSER"

# Determine what other processes have been given priority by admins
# and ought to be exempt [the next should be 1 line]
EXEMPTIONS=(`ps -auxo nice | awk '{print $1, $2, $11}' | grep -v root | grep -v nobody | grep -e - | awk '{print $2}'`)

# using /Users for real users instead of trying to get it from a tool, since 
#there is less worry about system users and no truncation
# Get names of users to be reniced 
SWITCHEDUSER=(`ls -1 /Users/ | grep -Ev '(.DS|.local|Shared)'`)

#rest as in original
# Renice: others to 15, main terminal to 0, priority processes to -15
#echo  ${SWITCHEDUSER[*]}
echo ${SWITCHEDUSER[*]} | xargs renice 15 -u
renice 0 -u $TOPUSER
echo ${EXEMPTIONS[*]} | xargs renice -15 -p

# Add additional rules...I renice my seti@home instances to 20

fi



[ Reply to This | # ]