Results 1 to 10 of 122

Thread: HOWTO: Set maximum CPU consumption in percentage by any process

Threaded View

  1. #8
    Join Date
    Apr 2008
    Beans
    41

    Re: HOWTO: Set maximum CPU consumption in percentage by any process

    Thanks for this. It was most helpful for my home media server ...

    I had to make some changes for my needs though as your method for polling for limited PIDs was always returning null... I ended up rewriting abit but the key change was the line:


    Code:
     LIMITED_PIDS=$(ps -eo args | gawk '$1=="cpulimit" {print $3}')
    ## changed to (more explaination below) ##
     LIMITED_PIDS=$(ps -eo args | grep cpulimited-bin |grep -v grep |awk '{print $3}')

    I needed a version with start/stop built in and also wanted logging.. So my finial code which is still being tested is:

    cpulimited.sh
    Code:
    #!/bin/bash
    # ==============================================================
    # CPU limit daemon - set PID's max. percentage CPU consumptions
    # ==============================================================
    # Variables
    CPU_LIMIT=25                   # Maximum percentage CPU consumption by each PID
    DAEMON_INTERVAL=3              # Daemon check interval in seconds
    LOG=/var/log/cuplimited.log
    CPULIMITED_TMPDIR=/tmp/cpulimited
    CONFIG=/etc/cpulimited/cpulimited.conf
    
    BLACKLIST=0
    WHITELIST=0
    PROCESSES_LIST=
    
    do_help() {
    cat <<EOF
    Usage:  $0 <options> start|stop
                         -f   ::  Run in foreground
           -c <config file>   ::  Use specified config file
    
    EOF
    exit 0
    }
    do_cpuwatcher() {
    
    # Search and limit violating PIDs
    while [ -z "$EXIT" ]; do
       sleep $DAEMON_INTERVAL
       # Check for exit
       DCMD=$(cat "$CONTROL_FILE" |tail -n 1)
       if [ "$DCMD" = "exit" ]; then
         echo "Shutdown requested..."
         PIDS="$(ps ax |grep cpulimited-bin |awk '{print $1}')"
         echo "Removing CPU limits ..."
         kill -9 $PIDS >/dev/null 2>&1
         sleep 1
         cd /tmp
         echo "Cleaning up ..."
         rm -rfd $CPULIMITED_TMPDIR
         echo "Goodbye"
         EXIT=1
         exit 0
       fi
       NEW_PIDS=$(eval "$NEW_PIDS_COMMAND")
       LIMITED_PIDS=$(ps -eo args | grep cpulimited-bin |grep -v grep |awk '{print $3}')
       QUEUE_PIDS=$(comm -23 <(echo "$NEW_PIDS" | sort -u) <(echo "$LIMITED_PIDS" | sort -u) | grep -v '^$')
       if [ -n "$QUEUE_PIDS" ]; then
         echo "These PIDs are already limited: $LIMITED_PIDS"
         echo "These PIDs are now entering the queue: $QUEUE_PIDS"
       fi
       for i in $QUEUE_PIDS; do
            echo "Setting limits for PID: $i"
            if [ -z "$FOREGROUND" ]; then
               ./cpulimited-bin -p $i -l $CPU_LIMIT -z >>$LOG 2>&1 &
            else
               ./cpulimited-bin -p $i -l $CPU_LIMIT -z &
            fi
       done
    done
    exit 0
    }
    
    
    # Init
    ##  Process commandline options
    while [ "$1" ]; do
       case "$1" in
         -f)
             FOREGROUND=1
             shift 1
          ;;
         -c)
             CONFIG=$2
             shift 2
          ;;
      start)
             CMD=start
             shift 1
             break
           ;;
       stop)
             CMD=stop
             shift 1
             break
          ;;
          *)
           do_help
           break
       esac
    done
    if [ -z "$CMD" ]; then
      do_help
      exit 0
    fi
    
    
    [ -f $CONFIG ] && . $CONFIG
    if [ $BLACKLIST = 1 -a $WHITELIST = 1 ]; then
       echo "Cannot use both whitelist AND blacklist.  Please check your config"
       exit 1
    else
       if [ "$BLACKLIST" = "yes" ]; then
         MODE=blacklist
         NEW_PIDS_COMMAND="top -b -n1 -c | grep -E '$BLACK_PROCESSES_LIST' | gawk '\$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
       fi
       if [ "$WHITELIST" = "yes" ]; then
         MODE=whitelist
         NEW_PIDS_COMMAND="top -b -n1 -c | gawk 'NR>6' | grep -E -v '$WHITE_PROCESSES_LIST' | gawk '\$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
       fi
       if [ -z "$MODE" ]; then
         MODE=supervisor
         NEW_PIDS_COMMAND="top -b -n1 -c | gawk 'NR>6 && \$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
       fi
    fi
    
    ##########  END Init ############
    
    
    case "$CMD" in
       start)
           echo "Starting up in $MODE mode ..."
           if [ -d $CPULIMITED_TMPDIR ]; then
             echo "Already running or stale tmp directory detected. Aborting ..."
             exit 23
           else
             mkdir -p $CPULIMITED_TMPDIR
             CONTROL_FILE="${CPULIMITED_TMPDIR}/control"
             chown -R root:root $CPULIMITED_TMPDIR
             chmod 700 $CPULIMITED_TMPDIR
             cd $CPULIMITED_TMPDIR
             CPULIMIT=$(which cpulimit)
             ln -s $CPULIMIT cpulimited-bin
             touch $CONTROL_FILE
             if [ -n "$FOREGROUND" ]; then
               # Do not fork
               do_cpuwatcher
             else
               # Fork into the background
               do_cpuwatcher >>$LOG &
             fi
           fi
           ;;
        stop)
            echo "Sending stop signal ..."
            CONTROL_FILE="${CPULIMITED_TMPDIR}/control"
            echo "exit" >$CONTROL_FILE
          ;;
    esac
    I set a temp directory up for the script and symlinked /usr/bin/cpulimit to ./cpulimited-bin to ease in grep'ing for cpulimit processes spawned by this script. I also added the ability to set changes from a config file. The other change is that BLACKLIST/WHITELIST is a mode toggle (0/1) and PROCESS_LIST would contain the strings to act on... Most all other changes were simply stylistic.

    Thanks again!
    Last edited by onemyndseye; December 17th, 2010 at 03:47 PM.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •