#!/bin/sh # # This script is based on work of mendel from # http://www.lafferty.ca/software/webshots/webshot # webshot: hackish thing to take a picture of a whole webpage. # # idea from sippey (http://www.sippey.com/2004/blog-snaps/) # inspiration from bradfitz # # usage: webshot url filename # # JPEG seems to be the best format. # # Modified by Dobrica Pavlinusic 2004-07-25 # - include signal grabbing # - dynamic vncserver display # - correct WindowID parsing # - wait for browser to load full page (useful on slow links) # # It will need follwing external utilities: # vncserver # mozilla-firefox # HEAD (part or LWP perl library, it can be commented out) # nc (netcat, to simulate web server) # xwininfo (standard part of X-clients) # import (part of ImageMagick package) # xdotool (much more useful than xwit for this purpose) # # It will create snapshot of following size W=1024 H=768 D=24 # and then resize it to (comment out to disable) #RESIZE=200x # turn locally visible server to watch progress DEBUG=0 if [ ! -z "$3" ] ; then echo "DEBUG turned on" DEBUG=1 D=8 fi # wait for $WAIT seconds for page to load WAIT=30 # some configurable paths BROWSER=mozilla-firefox XSERVER=Xvfb URL=$1 FILE=${2:-screenshot.jpg} FRAMESET="`mktemp`.html" PROFILE_DIR=`mktemp -d` PORT=8888 LOCAL_DISPLAY=$DISPLAY if [ -z "$URL" ] ; then echo "usage: $0 http://url.to.capture [screenshot.jpg]" exit 1 fi if [ -z "`which xdotool`" ] ; then echo "$0 need xdotool from http://www.semicomplete.com/blog/projects/xdotool/" exit 1 fi if [ -z "`which $XSERVER`" ] ; then echo "$0 really need $XSERVER to operate. please install it." exit 1 fi while netstat -ln | grep ":$PORT " >/dev/null ; do PORT=`expr $PORT + 1` done echo "### using port $PORT" echo -n "testing URL $URL " if HEAD $URL >/dev/null ; then echo "ok" else echo "FAILED" exit 1 fi DISPLAY_PORT=6042 while netstat -ln | grep ":$DISPLAY_PORT " >/dev/null ; do DISPLAY_PORT=`expr $DISPLAY_PORT + 1` done DISPLAY=:`expr $DISPLAY_PORT - 6000` echo "using DISPLAY=$DISPLAY" if [ "$DEBUG" == 1 ] ; then echo "using locally visible debug server on $LOCAL_DISPLAY" DISPLAY=$LOCAL_DISPLAY Xephyr -ac -screen ${W}x${H}x${D} $DISPLAY 2>/dev/null & else echo "starting $XSERVER" $XSERVER -ac -screen 0 ${W}x${H}x${D} $DISPLAY 2>/dev/null & fi if [ -z "$!" ] ; then echo "ABORT: can't start X server!" exit fi XSERVER_PID=$! echo "X server pid $XSERVER_PID" function kill_x_server() { echo "Killing server $XSERVER_PID" kill $XSERVER_PID rm -f $FRAMESET rm -fr $PROFILE_DIR trap '' EXIT exit 1 } trap 'kill_x_server' INT QUIT TERM SEGV EXIT # create frameset to load site and after site is loaded trigger this script cat > $FRAMESET < END_OF_FRAMESET echo "Using frameset html $FRAMESET" echo "preview available with: xwd -display $DISPLAY -root | xwud" echo "making 'Screenshot' profile in $PROFILE_DIR" $BROWSER -CreateProfile "Screenshot $PROFILE_DIR" 2>/dev/null | grep Success echo "launching browser $BROWSER with $URL" $BROWSER -P Screenshot -width $W -height $H -safemode $FRAMESET 2>/dev/null & BROWSER_PID=$! function kill_browser() { echo "Killing browser $BROWSER_PID" kill $BROWSER_PID echo "Killing server $XSERVER_PID" kill $XSERVER_PID rm -f $FRAMESET rm -fr $PROFILE_DIR trap '' EXIT exit 1 } trap 'kill_browser' INT QUIT TERM SEGV EXIT function ping_browser() { echo -n "ping browser" while ! ( $BROWSER -remote "ping();" 2>&1 ) >/dev/null ; do RID=`xdotool search Restore 2>/dev/null` if [ ! -z "$RID" ] ; then echo -n "Esc" xdotool focus $RID xdotool key Escape sleep 1 fi echo -n "." sleep 1 done echo " OK" } ping_browser # get Mozilla Firefox window id (for resize) WINDOW_ID=`xwininfo -display $DISPLAY -root -tree | grep gecko | cut -d\" -f1 | sort -n | head -1` if [ -z "$WINDOW_ID" ] ; then echo "can't find window with name 'Mozilla Firefox'" exit 1 else echo "working on firefox window $WINDOW_ID" fi xdotool search firefox xdotool focus $WINDOW_ID xdotool key F11 ping_browser $BROWSER -remote "openURL($FRAMESET)" 2>/dev/null echo "waiting for on_load event from browser $BROWSER_PID for ${WAIT}s" # there is hard-coded limit here: # we will wait $WAIT sec for page to load and render echo -e "HTTP/1.0 304 Not modified\r\n\r\n" | nc -l -w $WAIT -p $PORT >/dev/null || echo "Timeout after $WAIT sec!" # try to deduce inside area of window DUMP_ID=`xwininfo -display $DISPLAY -id $WINDOW_ID -tree | grep 0x | grep -v ${W}x${H} | grep ${W}x | head -1 | sed 's/^ *//' | cut -d' ' -f1` if [ -z "$DUMP_ID" ] ; then echo "can't find inside area of window. Using whole browser!" DUMP_ID=$WINDOW_ID fi echo "saving window $DUMP_ID to $FILE" if [ ! -z "$RESIZE" ] ; then RESIZE="-geometry $RESIZE" fi import -window $DUMP_ID $RESIZE $FILE if [ "$DEBUG" == 1 ] ; then echo -n "press enter to exit! " read fi