Home » Questions » Computers [ Ask a new question ]

Use cron to screen capture on Mac OS X

Use cron to screen capture on Mac OS X

To analyze my own computer usage, not to spy on anyone (although it crossed my mind), I want to have cron capture the current screen every minute.

Asked by: Guest | Views: 144
Total answers/comments: 2
Guest [Entry]

"If you look at the end of the screencapture manpage, you see it says:

To capture screen content while logged in via ssh, you must launch
screencapture in the same mach bootstrap hierarchy as loginwindow:

PID=pid of loginwindow
sudo launchctl bsexec $PID screencapture [options]

So I think you could do somethig like this in your shell script that cron calls:

loginwindowpid=`ps axo pid,comm | grep '[l]oginwindow' | sed -n 's# *\([^ ]*\).*$#\1#p'`
sudo launchctl bsexec $loginwindowpid screencapture /somedir/screen.png

Of course, you'll need your userid set to not need a password for sudo.
That is you'd set in /etc/sudoers with the visudo command

youruserid ALL=(ALL) NOPASSWD: ALL"
Guest [Entry]

"As an aside, I use Java for the same job. It starts on boot and I look through the images at the end of the day.

* Code modified from code given in http://whileonefork.blogspot.co.uk/2011/02/java-multi-monitor-screenshots.html following a SE question at
* http://stackoverflow.com/questions/10042086/screen-capture-in-java-not-capturing-whole-screen and then modified by a code review at http://codereview.stackexchange.com/questions/10783/java-screengrab
package com.tmc.personal;

import java.awt.AWTException;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

import javax.imageio.ImageIO;

class ScreenCapture {

static int minsBetweenScreenshots = 5;

public static void main(String args[]) {
int indexOfPicture = 1000;// should be only used for naming file...
while (true) {
takeScreenshot(""ScreenCapture"" + indexOfPicture++);
try {
} catch (Exception e) {

//from http://www.coderanch.com/t/409980/java/java/append-file-timestamp
private final static String getDateTime()
DateFormat df = new SimpleDateFormat(""yyyy-MM-dd_hh:mm:ss"");
return df.format(new Date());

public static void takeScreenshot(String filename) {
Rectangle allScreenBounds = getAllScreenBounds();
Robot robot;
try {
robot = new Robot();
BufferedImage screenShot = robot.createScreenCapture(allScreenBounds);
ImageIO.write(screenShot, ""jpg"", new File(filename + getDateTime()+ "".jpg""));
} catch (AWTException e) {
System.err.println(""Something went wrong starting the robot"");
} catch (IOException e) {
System.err.println(""Something went wrong writing files"");

* Okay so all we have to do here is find the screen with the lowest x, the
* screen with the lowest y, the screen with the higtest value of X+ width
* and the screen with the highest value of Y+height
* @return A rectangle that covers the all screens that might be nearby...
private static Rectangle getAllScreenBounds() {
Rectangle allScreenBounds = new Rectangle();
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] screens = ge.getScreenDevices();

int farx = 0;
int fary = 0;
for (GraphicsDevice screen : screens) {
Rectangle screenBounds = screen.getDefaultConfiguration().getBounds();
// finding the one corner
if (allScreenBounds.x > screenBounds.x) {
allScreenBounds.x = screenBounds.x;
if (allScreenBounds.y > screenBounds.y) {
allScreenBounds.y = screenBounds.y;
// finding the other corner
if (farx < (screenBounds.x + screenBounds.width)) {
farx = screenBounds.x + screenBounds.width;
if (fary < (screenBounds.y + screenBounds.height)) {
fary = screenBounds.y + screenBounds.height;
allScreenBounds.width = farx - allScreenBounds.x;
allScreenBounds.height = fary - allScreenBounds.y;
return allScreenBounds;