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

Pause and resume resource-intensive apps via script UNIX
Occasionally I find my computer tied up with some long-duration, resource-intensive application that one can't simply quit in the middle of. For example, iDVD can run for a couple days. Other times, on my family's multi-user machine, I'd like to be able to turn off other switched-out user's resource-hungry but idle apps (e.g. Word) that cause glitches when I'm doing something like using VLC Player or watching a QuickTime 480p movie.

Rather than quiting the app, I pause and later resume it by sending it Unix signals from the command line:
kill -s STOP 3328
The above command sends the STOP signal to, in this example, process 3328, which immediatly sleeps the process without aborting it. When I am ready to resume, I send it another signal to continue:
kill -s CONT 3328
Now you might be wondering why not simply use the commands nice and renice? Well two reasons. First, and primarily because, even at nice 19, sometimes that is not affirmative enough, espcially when the process is consuming resources other than the CPU: e.g. network intensive or disk intensive operations. Second, it's tricky to undo nicing and be sure you got it right.

[robg adds: We covered stopping processes in this earlier hint. This hint, however, provides an automated solution based on processor load -- read on for the details. Note that I have not tested this one.]

This can be automated too: here's a real life motivation. I like to run long duration apps on the home computer while I'm at work. But I don't want those apps getting in the way of other famliy members who might want the computers full attention while I'm away. Since they are not Admins, and my login is switched out, my rude application is dominating the computer.

If for example, I'm remotely backing up the computer, their web browsing experience will be sluggish. Thus I run this one-line perl script (which you can create an alias for) that watches the computer. Any time it detects a load above some threshold level, it stops the long duration application. (Remember, this is one line; it's been broken for a narrower display. There's a space at the end of each line; be sure to copy that as well.)
perl -we 'die unless @ARGV;$SIG{INT} =sub {`kill -s CONT $p`; die 
qq:bye now\n:};($p,$s,$c) = ( @ARGV,2.5,0.5);($sig,$w) = 
(qq:CONT:,30);$c1=$c2=$e1=$e2=0;$e2=30;while (1) { last unless  grep{ 
/^\s*$p /} `ps x`;  ($x,$y,$z) = split /\s+/,`sysctl vm.loadavg`; 
($sig,$w,$e1,$e2)=(qq:STOP:,300,300,0) if ($y>$s) ; ($sig,$w,$e1,$e2) 
=(qq:CONT:,30,0,30) if ($z<$c);`kill -s $sig $p` ; print STDERR qq/ $p: 
$x $y $z   $sig  S:$c1 C:$c2 sec                /,chr(13); sleep 
$w;$c1+=$e1;$c2+=$e2}'
So in this example, the three args on the command line are 3357, 2.3 and 0.5. In this case, 3357 is the process number of iDVD, 2.3 is the threshold load at which I want the process to stop, and 0.5 is the threshold load at which I want the process to resume.

Every 30 seconds, the script checks the load average for the last minute, and if it exceeds the upper threshold, it STOPs the process. Then every 300 seconds, it checks the load average for the last ten minutes, and if it's below the lower threshold, it continues the process.

What the best numbers for detecting computer use by load monitoring are will depend upon how your computer is used, and the application in question. Some computers are very busy even when they are nominally inactive, because users have so many things running in the background. And some long duration applications have very high loads even when they are the only thing running. You can figure this out by monitoring the load with top. And to make this convenient, the above perl script also displays the loads for you, so you can see what happens.

Caveats: Not every application is going to take kindly to being suspended. Also suspended apps are truly frozen. You can't quit them, or move their open windows, or bring them to the foreground, until you unsuspend them. Also note that some applications, such as ffmpegX, actually run in multiple forks, so deciding which process number to freeze is not always straightforward.
    •    
  • Currently 2.14 / 5
  You rated: 2 / 5 (7 votes cast)
 
[12,616 views]  

Pause and resume resource-intensive apps via script | 11 comments | Create New Account
Click here to return to the 'Pause and resume resource-intensive apps via script' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Pause and resume resource-intensive apps via script
Authored by: SOX on May 17, '06 08:28:11AM
Replying to my own hint here. it looks like the editor accidentally chopped off the three command line args from the hint. so the three numbers I referred to in the hint were supposed to follow that one line perl script.

A couple notes about that script. The script is polite in that if you break out of it with control-C, it will leave your app in a running state, not suspended. Additionally, if your application quits then the script eventually notices this and terminates itself, thus you can set this to run in the background if you want. It won't bother the script if, in another window you suspend or continue the application, so you still can have some fine grained manual control if you need it. And you can run as many copies of this as you wish to control other applications. Nothing dire will happen if you mistakenly run this twice to control the same job, thought that's not the reccomended use.

Now as for converting this into an alias to make it handy to use, here is a version of it I have escaped all the special characters to allow you to do this easily. Cut and paste the following verbatim into a terminal window--you should do this as one single cut and paste not a line at a time. finish with a carriage return from the keyboard.


alias supernice perl\ \-we\ \'die\ unless\ \@ARGV\;\$SIG\{INT\}\ \=sub\
 \{\`kill\ \-s\ CONT\ \$p\`\;\ die\ qq\:bye\ now\\n\:\}\;\(\$p\,\$s\,\$c\)\
 \=\ \(\ \@ARGV\,2\.5\,0\.5\)\;\(\$sig\,\$w\)\ \=\ \(qq\:CONT\:\,30\)\;\
 \$c1\=\$c2\=\$e1\=\$e2\=0\;\$e2\=30\;while\ \(1\)\ \{\ last\ unless\
 \ grep\{\ \/\^\\s\*\$p\ \/\}\ \`ps\ x\`\;\ \ \(\$x\,\$y\,\$z\)\ \=\ split\
 \/\\s\+\/\,\`sysctl\ vm\.loadavg\`\;\ \ \(\$sig\,\$w\,\$e1\,\$e2\)\
 \=\(qq\:CONT\:\,30\,0\,30\)\ if\ \(\$z\<\$c\)\;\(\$sig\,\$w\,\$e1\,\
 \$e2\)\=\(qq\:STOP\:\,300\,300\,0\)\ if\ \(\$y\>\$s\)\ \;\ \`kill\ \-s\
 \$sig\ \$p\`\ \;\ print\ STDERR\ qq\/\ \$p\:\ \$x\ \$y\ \$z\ \ \ \$sig\
 \ S\:\$c1\ C\:\$c2\ sec\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \/\,chr\(13\)\;\ sleep\
 \$w\;\$c1\+\=\$e1\;\$c2\+\=\$e2\}\'

To use this after installing that alias you would type at the command line


supernice  3357  3.0 0.5
where 3357 is the name of whatever process you want to supernice, and 3.0 is the upper load limit trip where you want it to stop, and 0.5 is the lower load limit trip where you will let it resume after being stopped. Fill in your own numbers as appropriate.

Output from the script will display the number of seconds the job has been stopped and how long it has been running since supernice was invoked. It also displays the load levels for the last 1 minute and last ten minutes. These numbers update every 30seconds when in CONT mode or 5 minutes in STOP mode.

[ Reply to This | # ]

Pause and resume resource-intensive apps via script
Authored by: SOX on May 17, '06 08:50:12AM
Here's an annotated verison of the script that could be saved to a file instead of being an command line alias.

#!/usr/bin/perl -w
# expects 3 args: job#  high_load_trip  Low_load_trip

die unless @ARGV;    # exit if no args on command line

# install a signal handler to assure the watched job is left running if the user breaks out of this script.
$SIG{INT} =sub {
              `kill -s CONT $p`; 
              die  qq:bye now\n:
              };

# get the args.  use default args for trip value if there is only one arg on command line
($p,$s,$c) = ( @ARGV,2.5,0.5);

# initialize state and wait period to "continue" and 30 seconds
($sig,$w) = (qq:CONT:,30);

# initialize the counters
$c1=$c2=$e1=$e2=0;$e2=30;

# main loop.
while (1) { 
       # see if wathced process is still in the process list and
       # gracefully exit if it it not there any more.
       last unless  grep{ /^\s*$p /} `ps x`;

      # read and parse the load averages for last 1 an ten minutes
      ($x,$y,$z) = split /\s+/,`sysctl vm.loadavg`; 

      #  if the 1 minute load average ($y)  is above the high_trip ($s) 
      # then set the state to STOP and the wait increment to 300 seconds
      ($sig,$w,$e1,$e2)=(qq:STOP:,300,300,0) if ($y>$s) ;

      # on the other hand if the 10-minute load average is less then the low_trip
      # the set the state to CONT and the wait increment to 30 seconds
      ($sig,$w,$e1,$e2) =(qq:CONT:,30,0,30) if ($z<$c);

      # otherwise just continue doing what ever you did last

       # send the signal to CONT or STOP to the job
       `kill -s $sig $p` ;

       # display state on terminal and snooze
       print STDERR qq/ $p: $x $y $z   $sig  S:$c1 C:$c2 sec                /,chr(13); 
       sleep $w;  

       # increment counters.
       $c1+=$e1;$c2+=$e2
}


[ Reply to This | # ]
Thanks
Authored by: Felix_the_Mac on May 17, '06 12:23:52PM

Just wanted to say thanks for sharing this.
It looks like a nice piece of work.



[ Reply to This | # ]
Thanks
Authored by: SOX on May 17, '06 12:49:58PM

you're welcome, and thanks for mentioning it, I appreciate it.



[ Reply to This | # ]
Pause and resume resource-intensive apps via script
Authored by: vincentvanwylick on May 18, '06 12:32:38AM

Thanks for the hint. But how do I save it as a file, I'm pretty new at this scripting thing. Script Editor gives me the Syntax error: "an unknown token can't go there," and I can't seem to save the file.



[ Reply to This | # ]
Pause and resume resource-intensive apps via script
Authored by: DylanMuir on May 18, '06 01:02:01AM

You should just use a text editor, and save the file as plain text (with the ".pl" extension). Then you will need to make the script executable from the terminal using chmod +x scriptname.

DRM



[ Reply to This | # ]
Pause and resume resource-intensive apps via script
Authored by: SOX on May 18, '06 07:20:08AM
you can save the third (annotated) version above as an executable file like this: highlight all the text and select copy. Open up a terminal windows and type:

pbpaste > supernice.pl
chmod a+x supernice.pl
Now it's ready to run by typing:

./supernice.pl  3357 3.0 0.5
where those numbers are the process ID and the hi-lo load limits on the application you want to limit. use top or activity monitor to find the process ID.

Another way that might be slightly easier is to add this to your .cshrc or .bashrc file.

to do this copy the second form above (the one that starts with "alias supernice ...). grab all the lines in one selection. If possible select carriage returns before and after it, though this is not essential. select "copy", then open a terminal window and type:


pbpaste >> ~/.cshrc
pbpaste >> ~/.bashrc
note the double "greater than" symbols, the tilde and the period.

Now close that terminal window and open a new one (to force it to re-initialize). At this point you should be able to try


supernice  3347 3.0 0.5
and have it supernice process ID 3347 for example. Notice that in this form you don't need to specify the ".pl" suffix or the "./" prefix, since this is now a built-in alias command, not a script file. It can be run from any subdirectory, not just the directory where the script file was located.

to remove the alias if you do something wrong or simply don't like it, open the .bashrc and .cshrc in any text editor and delete the offending line. To open a hidden dot file in TextEdit you can type:


open -a TextEdit ~/.cshrc


[ Reply to This | # ]
Pause and resume resource-intensive apps via script
Authored by: SOX on May 18, '06 08:08:19AM

Alternatively see the applescript version I posted below



[ Reply to This | # ]
just use app stop
Authored by: nick on May 18, '06 05:36:03AM

a nice menu-bar programm to pause and resume apps.

http://www.versiontracker.com/dyn/moreinfo/macosx/26895



[ Reply to This | # ]
just use app stop
Authored by: SOX on May 18, '06 07:23:59AM

Nice app, thanks for the pointer. But you missed the whole point of the post I think. Perhaps the title was misleading. The point of the post was to have the apps suspend and resume automatically depending on the load of the computer, not simply to have manual control over the running state.



[ Reply to This | # ]
Applescript
Authored by: SOX on May 18, '06 08:07:01AM
here's an apple script wrapped version of this.

set ttt to " 3.0 0.4"
display dialog "Process_ID  High_load_stop Low_load_continue" default answer ttt
set ttt to the text returned of the result

set command to "perl -we 'exit 0 if fork; die unless @ARGV;$SIG{INT} =sub {`kill -s CONT $p`; die qq:bye now:};($p,$s,$c) = ( @ARGV,2.5,0.5);($sig,$w) = (qq:CONT:,30);$c1=$c2=$e1=$e2=0;$e2=30;while (1) { last unless  grep{ /^\\s*$p /} `ps x`;  ($x,$y,$z) = split /\\s+/,`sysctl vm.loadavg`; ($sig,$w,$e1,$e2)=(qq:STOP:,300,300,0) if ($y>$s) ; ($sig,$w,$e1,$e2) =(qq:CONT:,30,0,30) if ($z<$c);`kill -s $sig $p` ; print STDERR qq/ $p: $x $y $z   $sig  S:$c1 C:$c2 sec                /,chr(13); sleep  $w;$c1+=$e1;$c2+=$e2}' " & ttt 

do shell script command

paste this into the applescript editor then same it as an application. please note that the perls script part of this needs to be on a single line with no line breaks. This launches a background process to watch the app. The downside of this is there is no feedback about the run-state of the application as provided by the command line version. You can still use top to monitor it however.

[ Reply to This | # ]