Take Screenshot and Send It to Web Server

A previous post explained how to create a CUPS printer which sends it output as a bitmap images to a web server. This small script gives an example how to post screenshots to the same server backend. The script utilises scrot to take a screenshot and curl to send the image file to the server.

#!/bin/bash

# Takes screenshot (using scrot) and transmit it to server via http (curl)

URL=http://your.server/your/path/index.php

TEMPFILE=`/bin/tempfile --suffix=.jpeg`
echo "Temporary file: ${TEMPFILE}"

/usr/bin/scrot ${TEMPFILE}

/usr/bin/curl -i -F username=${USER} -F page0=@${TEMPFILE} ${URL}
CURL_EXIT=$?

if [ ${CURL_EXIT} -eq 0 ]; then
    zenity --info --text="Kuvan lähetys onnistui"
else
    zenity --error --text="Virhe kuvan lähettämisessä: ${CURL_EXIT}"
fi

rm ${TEMPFILE}

Show Active Window Name (Python, Tk)

This small Python application shows active window name.

#!/usr/bin/python

# This program is Public Domain
# Make sure you have installed xdotool before executing this (Debian/Ubuntu package "xdotool")

import os
from Tkinter import *

root = Tk()
# This Tk string holds the message string
message = StringVar()
message.set("none")

# Store update ID to this global var
update_id=None

# Show label and get content from variable "message"
w = Label(root, textvariable=message)
w.pack()

# Create Exit button
button_cancel = Button(root, text="Dismiss", command=root.quit)
button_cancel.pack()

def update_message():
    message.set(os.popen('/usr/bin/xdotool getwindowfocus getwindowname').read())
    update_id=root.after(1000, update_message)

update_id=root.after(1000, update_message)
root.mainloop()

CUPS Backend Creates Bitmaps to Web Server

This set of scripts explore how to make a CUPS printer which actually sends the print job as a bitmap (jpeg) files.

The CUPS backend is written in bash and uses:

  • GhostScript to render the PostScript print job to jpeg
  • cURL to send the jpeg files to server
  • notify-send to interact with the user (but I haven’t been able to get this work)

The server software is written in PHP and:

  • needs a httpd-writeable path for resulting files (e.g. ./files/)

Install

The zip file contains all necessary scripts.

CUPS backend

cp meb /usr/lib/cups/backend
chown root.root /usr/lib/cups/backend/meb
chmod 744 /usr/lib/cups/backend/meb

Receiving Server

  • Place the server file (index.php) to whatever location to your PHP-enabled web server
  • Create a directory for job files and make this writeable to your web server
  • Edit the $FILES_PATH to point to this directory (relative paths are ok)

Create the CUPS printer

Create the CUPS printer with following command:

lpadmin -p [PRINTER_NAME] -m postscript -v "[SERVER_URI]" -D "[DESCRIPTION]" -L "[DESCRIPTION]" -E -P ./Generic-PostScript_Printer-Postscript.ppd -o PageSize=A4
  • [PRINTER_NAME] is the name of your printer (e.g. “demoprn”)
  • [SERVER_URI] points to the index.php (e.g. “meb://yourhost/path/to/index.php”). Note that the backend contacts the server with http (not https).
  • [DESCRIPTION] is the printer description (-D) and location (-L) shown to the user (e.g. “Bitmap Test Printer”)
  • You’ll get the ppd file from openprinting.org:
    • Select “Generic PostScript Printer”
    • Select “download”
    • Click “Generate PPD file”

Testing

Now your should see the newly created printer. You may debug the printing process from /tmp/meblog.txt.

Discussion

Technically speaking the approach works. The client sends the bitmap files to server which stores them.

The script is able to send the progress notifications to the user using notify-send (Debian package libnotify-bin). For this the backend searches the user’s DBUS_SESSION_BUS_ADDRESS environment variable from the user’s process information.

For some reason my installation produced hanging /tmp/foomatic-XXXXXX files. No idea who does not take care of its cleanup.

The http upload fails if the number of pages is high and therefore the size of the resulting files exceed the maximum settings in your php.ini (upload_max_filesize and post_max_size).

Kill Processes Using a Filesystem

In my home depot I share files to laptops using NFS over a VPN network. Typically the shutdown process hangs as there appears to be processes using the mounted NFS filesystem no matter whatever orders I give to the shutdown scripts. After getting tired of debugging the shutdown process I decided to write a pre-shutdown script that kills all processes with open files in the NFS fs.

The local fileserver is called “harkko”.

#!/bin/bash

function lsof_kill {
        MOUNT=$1

        for THIS_PID in $(lsof 2>/dev/null | grep -i "${MOUNT}" | awk '{print $2}')
        do
                kill -KILL ${THIS_PID}
        done
}

echo "Killing processes with open files at mounted NFS filesystems..."

# Kill all processes with open files at /mnt/harkko
lsof_kill /mnt/harkko

# Kill all processes with open files at /mnt/huge
lsof_kill /mnt/huge

# Kill all processes with open files at /mnt/canister
lsof_kill /mnt/canister

echo "...done"

echo "Executing harkko_umount"
harkko_umount

echo "Stopping harkko VPN"
/etc/init.d/openvpn stop harkko

echo "Executing poweroff"
poweroff

Downloading Abitti Disk Images

Abitti is a testing system developed by Matriculation Examination Board of Finland. The system is based on bootable USB memories which contain a live Linux with pre-installed test system.

Officially Abitti supports USB memory downloading and writing though a Windows application AbittiUSB. However, abitti_dlimg.sh downloads, checks and unpacks the dd image files.

Changelog:

  • 7.2.2015 Initial version

Running iperf to your network

Lets think that you have a LAN with a DHCP server and a number of clients (i.e. a computer lab). For whatever reasons you want to test your LAN bandwidth between your server and clients simultaneously. This can be done with iperf which is a standard tool in a typical Linux distribution. In this example we’re using Debian/Ubuntu.

Preparation in the Client Side

Install iperf:

# apt-get install iperf

At this point you might want to decide a port number for iperf clients (which really are servers but running in the clients). In this example we use 6001. To make sure only your DHCP host may execute the tests you may want to allow traffic to port 6001 (both UDP and TCP) only from your host.

Add following line to your /etc/rc.local just above “exit 0”:

start-stop-daemon --start -x /usr/bin/iperf -n iperf -b -- -s --udp -p 6001

This starts the iperf on boot in your client. It sits waiting the server to connect.

Running the Test from the Server Side

In my server I use dnsmasq as a DHCP server. It reports all DHCP activity in /var/log/syslog. In order to get all IP addresses given to the clients after the last logrotate enter following command:

#!/bin/sh

IP_ALL=`grep DHCPACK /var/log/syslog | grep -o -P "\d+\.\d+\.\d+\.\d+"`

# Go through IP_ALL and ping all IPs. Collect online IPs to IP_UP.

for this_ip in $IP_ALL
do
        # Check with PING
        echo -n "pinging: $this_ip   "
        this_count=0
        this_count=$(ping -c 1 $this_ip | grep 'received' | awk -F',' '{ print $2}' | awk '{ print $1}')

        if [ $this_count -eq 1 ]; then
                # this_ip is up
                IP_UP="$IP_UP $this_ip"
                echo "up"
        else
                echo "down"
        fi
done

# Go through IP_UP and run iperf to them

for this_ip in $IP_UP
do
        echo -n "starting iperf: $this_ip   "
        iperf -c $this_ip -p 6001 -t 10 --udp -b 100k -d -y csv >/tmp/bwtest.csv 2>&1 &
        echo "done"
done

# Wait for iperf processes to end
PROC_COUNT=1
until [ $PROC_COUNT -eq 0 ]
do
        sleep 1
        PROC_COUNT=`ps | grep -c "iperf"`
        echo -n "Processes running: $PROC_COUNT\r"
done

echo ""