cheatsheet.zwischenspeicher.info

Some tech documentation and snippets, finally organized.

X11 screencast (with audio)

Screenrecording of a 1024x768 pixel area, with an x/y-offset of 80/120px. Sound is recorded at a bitrate of 128kb/s from the analog input of the default ALSA sound card, the outline of the captured region is displayed on screen:

avconv -f x11grab -show_region 1 \
       -s 1024x768 -i :0.0+80,120 \
       -f alsa -i hw:0 \
       -b:v 1200k -b:a 128k \
       -y ~/screencast.mpg

Don't forget to check the mixer settings!


Recording sound from another application instead of an external source requires to modprobe the snd_aloop kernel module and a line of ALSA configuration:

### File: ~/.asoundrc

pcm.!default { type plug slave.pcm "hw:Loopback,0,0" }

Additionally, the avconv audio input parameters need to be changed to

-f alsa -i hw:Loopback,1,0

The configuration of an optional output channel for audio monitoring is described here at ffmpeg.org.

ALSA: changing audio device priority

ALSA enumerates available audio devices in the order their corresponding kernel modules are loaded, so e.g. connecting an audio capable HDMI device can break on-board sound. For a permanent and system wide change of audio device priority, this order can be manipulated by adding a simple configuration file with the suffix .conf to the folder /etc/modprobe.d/.

First it needs to get a list of the loaded sound modules:

$ cat /proc/asound/modules
 0 MODULE_X
 1 MODULE_Y
 2 MODULE_Z

In the best case, all audio devices use different kernel modules, which will be listed, one per line, with the key options and an index value:

### File: /etc/modprobe.d/alsa.conf

options MODULE_1 index=0
options MODULE_2 index=1
options MODULE_3 index=2

If there are several audio devices based on the same chipset, additionally their associated card IDs need to be specified. The command

$ aplay -l | grep ^card

will return the necessary identifiers in the second column, right after card #:. Add them to the respective lines in /etc/modprobe.d/alsa.conf as new column three, between module name and index number.

To be prepared for the occasional use of a USB audio adapter, I suggest to additionally list the snd-usb-audio module and assign it index=0.

Here my current configuration:

### File: /etc/modprobe.d/alsa.conf

options snd-usb-audio               index=0
options snd-hda-intel   id=VT82xx   index=1
options snd-hda-intel   id=HDMI     index=2

Although this is Linux, the easiest way to make the changes take effect is to reboot the system ;)


If you have several devices with the same ID, you can make ALSA directly address the hardware by adding the following entries to /etc/asound.conf or ~/asoundrc - the respective card number can again be determined with the command aplay -l.

### File: /etc/asound.conf 
###       OR
###       ~/.asoundrc

pcm.!default {
    type hw
    card 1
}

ctl.!default {
    type hw
    card 1
}

Note: This way no other applications can access the sound card concurrently.


As a last solution, it is possible to fully disable specific cards with a line like the following in /etc/modprobe.d/alsa.conf:

### File: /etc/modprobe.d/alsa.conf

options snd-hda-intel   enable=0,1

The array will disable (0) the first and enable (1) the second of two cards.

Auto-upgrade for Debian based systems

A reliable auto-updater for home use. It can be executed e.g. at boot from /etc/rc.local to keep apt based systems up-to-date. Some output will be logged to /var/log/safe-upgrade.log, in case of upgraded or held packages as well as errors a report will be sent to root@localhost.

Update August, 2020: Command line option "--full" for Dist-Upgrade.
Update June, 2022: sleep-loop for delayed connections (dial-up, WiFi).

#!/bin/sh
#
# safe-upgrade.sh
#
# automated "safe-upgrade" for apt-based distributions with logging
# to /var/log/safe-upgrade.log and a mail to root@localhost in case
# of upgraded packages or problems
# optional command line parameter "--full" will run a dist-upgrade

pingtest=debian.org
hostname=`hostname`
logfile=/var/log/safe-upgrade.log
mailto=root@localhost

if [ X"$@" = X"--full" ] ; then
        task=dist-upgrade
else
        task=upgrade
fi

sleep 15
echo ----- `date` ----- >> "$logfile"
ping -c 1 "$pingtest" > /dev/null 2>> "$logfile" ||\
    {
        echo "System upgrade cancelled: No internet connection." |\
        tee -a "$logfile" |\
        mailx -s "$hostname"\ update\ \*\*\*ERROR\*\*\* "$mailto"
        exit 0
    }
DEBIAN_FRONTEND=noninteractive
apt-get -q=2 update 2>&1 |\
    tee -a "$logfile" |\
    mailx -E -s "$hostname"\ update\ \*\*\*ERROR\*\*\* "$mailto"
apt-get "$task" -y -q 2>&1 |\
    grep -ve "^(\{0,1\}Reading" \
         -e "^Building" \
         -e "^Calculating" |\
    tee -a "$logfile" |\
    grep -ve "^0 upgraded.*0 not upgraded\.$" |\
    mailx -E -s "$hostname"\ upgrade\ log "$mailto" &&
echo ----- DONE ----- >> "$logfile"
exit 0

To tame the daily growing log file, add the following lines to /etc/logrotate.conf or into an own file in /etc/logrotate.d/. This will keep compressed archives of the last three months' log files.

### File: /etc/logrotate.conf

/var/log/safe-upgrade.log {
    monthly
    create
    rotate 3
}

If you want the script to be executed by cron, it is necessary to set the $PATH variable - in the script itself, or in the crontab. This example runs every three hours at 45':

### File: root crontab, open to edit with "crontab -e"

# m h  dom mon dow   command
45 */3 * * * PATH='/usr/sbin:/usr/bin:/sbin:/bin' /path/to/safe-upgrade.sh

Piping dd

Write to several devices at once with dd and tee:

$ dd if=INFILE | tee > (dd of=/dev/sdX) | dd of=/dev/sdY

dd over the network with netcat and bzip compression (not encrypted),
serverside...

$ nc -l 9000 | bzip2 -d | dd bs=1M of=OUTFILE

...and clientside:

$ dd bs=1M if=INFILE | bzip2 -c | nc SERVER 9000

Writing data to an ssh server, using xz transport compression:

$ dd if=INFILE bs= 1M | xz |\
    ssh user@host "xz -d | dd of=OUTFILE bs=1M"

Reading data from an ssh server, again with xz transport compression:

$ ssh user@host "dd if=INFILE bs=1M | xz" |\
    xz -d | dd of=OUTFILE bs=1M