One-liner to duplicate database over network

Here is a handy little bash pipeline that I used to transfer a MariaDB database from a development system (in the USA) to the production system (in Europe).  It’s really a one liner, but this website isn’t wide enough to display it all on one line:

mysqldump -u root --password=<password> --databases <databases> |
ssh <user@target> "mysql -u root --password=<password>"

Note that this will drop any existing database on the target system with the same name as the one being duplicated.

If you use public-key cryptography rather than passwords for ssh authentication, then this will run with no user input necessary at all.

For a demonstration, use the following shell scripts:

Script to create example database:

#!/usr/bin/env sh
mysql -u root -p <<quit
create database lemon;
use lemon;
create table lime (field1 VARCHAR(32), field2 int);
insert into lime values ("zesty", 42);
quit

Script to copy example database to another system:

#!/bin/bash

# Prompts the user for input, stores input in variable, uses existing value if
# user provides no input.
# Parameters: prompt, default value, variable name, [optional: silent?]
function prompt {
        local def line silent
        def="$2"
        [ -z "$def" ] && def=`eval echo -n '$'"$3"`
        [ -z "$def" ] && val="" || val=" ($def)"
        echo -n "$1$val: "
        [ "$4" ] && silent="-s" || silent=""
        read $silent line
        [ -z "$line" ] && eval $3="$def" || eval $3="$line"
        [ "$silent" ] && echo ""
}

# Default values
DBNAME=lemon
DBUSER=root
DBPASS=
SSHOST=

# Get input from user
prompt "Database name" "$1" DBNAME
prompt "Database username" "$2" DBUSER
prompt "Database password" "" DBPASS "-s"
prompt "SSH target host" "$3" SSHOST

# A nice one/two-liner (well one-line if you replace the variables with useful
# values, and ditch the above code)
mysqldump -u "$DBUSER" --password="$DBPASS" --databases "$DBNAME" |
ssh "$SSHOST" "mysql -u \"$DBUSER\" --password=\"$DBPASS\""

This script assumes that an SSH server is enabled on the target machine, and that the MySQL root passwords are the same on both systems.

Then to see the copied database (run on the target system):

echo "select * from lemon.lime;" | mysql -p

Or if you can’t be bothered opening an interactive shell on the target system:

echo "select * from lemon.lime;" | ssh <user@target> "mysql -p"

Wake-on-lan remote interface

This software provides a way to wake (via wake-on-lan) machines on a remote network.

After making my home PC accessible externally via Dynamic DNS, I needed a way to remotely power it on and off, since leaving it on 24/7 would run up a large energy bill.  I took one of my (many) Raspberry Pi computers and set up a script to log the MAC addresses of all machines detected on the network, along with corresponding IP addresses and hostnames.  This script runs periodically as a cron job, providing a list of machines by name or last known IP, and their associated MAC addresses.

A web interface allows any PC from this database to be chosen, and for a wake-on-lan magic packet to be dispatched to it.  Provided the PC is connected to the network via an ethernet cable and wake-on-lan is enabled on the associated adapter, the end result is that the chosen PC will turn on in response to me clicking a button in my web browser from 40 miles away.

The PC must be wired into the network in order to receive wake-on-lan packets, but there can be wireless links between the router/switch that the PC is wired to and the Raspberry Pi.  Wake-on-LAN magic packets are sent as UDP broadcasts in my script, although they could be in any type of container that will get routed to the target PC’s ethernet port.

Download: Remote Wake-on-LAN, MAC database scripts and web interface
Latest version (github): battlesnake/macs

Dynamic DNS server

This software provides a cheap dynamic DNS solution for anyone with a Linux VPS (or a friend who is willing to share one).

I occasionally want to access my home PC while I’m away from home, but my ISP doesn’t offer static IP addressing.  Thanks to a resurgence in the popularity of virtualisation, servers are extremely cheap to rent nowadays (as little as £3/month).  In addition to the server hosting this website (and others), I run a DNS nameserver (using PowerDNS) on one of my other virtual servers.  With this simple BASH script and a web interface, my server gained dynamic DNS capabilities and allows me to access my home PC despite the varying IP address.

The packaged script and web interface run on the nameserver, and a separate script is run on the target machine (in my case, the home PC), which curl’s the web interface periodically to update the necessary A-record.  It is important for the A-record to have a small TTL value (e.g. 60 seconds), in order to allow updates to propagate through DNS caches at a reasonable speed.  Look at the code for the PHP web interface to understand the syntax for the CURL request.

Rather than leave the home PC on 24/7 and waste electricity, I also created a remote interface to dispatch wake-on-lan packets.

Download: Dynamic DNS scripts
Latest version (github): battlesnake/ddns