Preserve the Shell Environment Using sudo

When executing a command or script as another user, it may be necessary to preserve the current shell’s environment. sudo provides the -E flag for this.

However, on Ubuntu systems the PATH environment variable is not preserved by the -E flag. Work around this by passing the current shell’s PATH environment variable on the command-line in the form of PATH=$PATH.

$ sudo PATH=$PATH -E -u anotheruser ./some-command.sh

There are other ways to manage environment variables with sudo by editing /etc/sudoers (use sudoedit, don’t edit it directly!), but the above can be useful to quickly get the job done.

Tags: ,

Setting date and time on Debian and Ubuntu

The Linux date command can take several formats to set the system date andtime.

Here’s the format that I use when setting the date and the time:

mmddHHiiYYYY.ss

where,

mm = month
 dd = day of month
 HH = hour in 24 hour format
 ii = minutes
 ss = seconds

The following is an example usage using the date and time, 22nd May 2012, 11:57am, respectively:

$ sudo date&nbsp_place_holder;052211572012.00

If only the time needs to be set then use the -s flag as follows:

$ sudo date&nbsp_place_holder;-s&nbsp_place_holder;"11:57:00"

If the system’s time zone requires changing, then on Debian-based systems use:

$ sudo dpkg-reconfigure tzdata
Tags:

WiFi Configuration On Ubuntu Workstation/Server

802.11g Wireless Networking

A recent change of office required some wireless networking, involving installation of TP-Link TL-WN321G USB dongles on an Ubuntu Linux 9.10 workstation, 8.04 server and a couple of Windows XP workstations. This article summarises getting the device to work on an Ubuntu Linux system.

I broadly followed the (out-of-date) Ubuntu Community Documentation Wifi How To, with a few tips from elsewhere, and a recollection that it’s sometimes better to be without Gnome’s Network Manager.

Kernel Driver Support

After plugging in the dongle, `lsusb` gave the following (snipped)
information:

$ lsusb
 Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
 Bus 001 Device 002: ID 148f:2573 Ralink Technology, Corp. RT2501USB Wireless Adapter
 ...

The second line of output gives the vendor (148f) and product (2573)
identifiers for the device. Checking a Linux wireless adapter chipset directory showed that supporting kernel drivers exist for this device’s chipset.

Listing the currently loaded kernel drivers showed that both the rt73usb and rt2500usb drivers had been automatically loaded:

$ lsmod
 Module Size Used by
 ...
 rt73usb 26336 0
 rt2500usb xxxxx 0
 ...

Seeing that two drivers had been loaded I chose to blacklist one of them – the rt2500usb. For that I created a new, custom blacklist file in the /etc/modprobe/ directory, avoiding editing any existing blacklist file that my distribution had created. I chose to create the file /etc/modprobe/blacklist-custom.conf:

$ cat /etc/modprobe.d/blacklist-custom.conf
 blacklist rt2500usb

The rt2500usb driver may work, though I haven’t tested it.

Gnome Network Manager Problems

The Ubuntu workstation default setup makes use of Gnome Network Manager to manage wired and wireless network connectivity. Inspecting the kernel message log showed that although the wireless interface was being activated, it was then very quickly deactivating:

$ dmesg
 ...
 [ xxxx.xxxxxx] rt73usb 1-2:1.0: firmware: requesting rt73.bin
 [ xxxx.xxxxxx] ADDRCONF(NETDEV_UP): wlan2: link is not ready
 [ xxxx.xxxxxx] wlan2: authenticate with AP xx:xx:xx:xx:xx:xx
 [ xxxx.xxxxxx] wlan2: authenticated
 ...
 [ xxxx.xxxxxx] wlan2: deauthenticating by local choice (reason=3)
 ...

Suspecting that Network Manager may be trying to maintain a wired-only connection and knowing the workstation doesn’t move anywhere, I decided to dispense with the network-manager package altogether:

$ sudo apt-get remove network-manager
 ...

Network Interface Configuration

In order to test the connection with my WAP I first disabled authentication and encryption on the WAP through its configuration interface. Here’s the simple configuration details for the USB dongle in the workstation’s /etc/network/interfaces file:

auto lo
    iface lo inet loopback
    address 127.0.0.1
    netmask 255.0.0.0

auto wlan2
    iface wlan2 inet static
    address 192.168.1.115
    netmask 255.255.255.0
    gateway 192.168.1.1
    # Wireless config
    wireless-essid myssid
    wireless-channel 1
    wireless-mode managed

Using iwconfig I could see that the USB dongle was connecting to the WAP.

Now that we know that we can connect to the wireless access point, we can protect our communication. I’m using WPA2 to connect to and encrypt the communication channel to my WAP. Here’s the snipped /etc/network/interfaces:

auto lo
iface lo inet loopback
    address 127.0.0.1
    netmask 255.0.0.0

auto wlan2
iface wlan2 inet static
    address 192.168.1.115
    netmask 255.255.255.0
    gateway 192.168.1.1
    # WPA2 config
    wpa-psk secretpasskey
    wpa-driver wext
    wpa-key-mgmt WPA-PSK
    wpa-proto WPA2
    wpa-ssid myssid
    pre-up sleep 5

WPA2 details can go straight into the interfaces file, though you may wish to externalise the WPA2 supplicant information into a separate file that is read-protected from anything but the root user and group.

A check of the network interfaces shows a working wlan network interface:

$ ifconfig
lo Link encap:Local Loopback
    inet addr:127.0.0.1 Mask:255.0.0.0
    inet6 addr: ::1/128 Scope:Host
    UP LOOPBACK RUNNING MTU:16436 Metric:1
    RX packets:33 errors:0 dropped:0 overruns:0 frame:0
    TX packets:33 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:0
    RX bytes:1831 (1.8 KB) TX bytes:1831 (1.8 KB)

...

wlan2 Link encap:Ethernet HWaddr xx:xx:xx:xx:xx:xx
    inet addr:192.168.1.115 Bcast:192.168.1.255 Mask:255.255.255.0
    inet6 addr: fe80::227:19ff:feb7:668a/64 Scope:Link
    UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
    RX packets:468550 errors:0 dropped:0 overruns:0 frame:0
    TX packets:398811 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:406451098 (406.4 MB) TX bytes:184734469 (184.7 MB)

Checking wireless connection information with iwconfig shows the wlan interface is connected:

$ iwconfig
lo no wireless extensions.

...

wmaster0 no wireless extensions.

wlan2 IEEE 802.11bg ESSID:"myssid"
    Mode:Managed Frequency:2.462 GHz Access Point: xx:xx:xx:xx:xx:xx
    Bit Rate=54 Mb/s Tx-Power=9 dBm
    Retry long limit:7 RTS thr:off Fragment thr:off
    Power Management:on
    Link Quality=38/70 Signal level=-72 dBm
    Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
    Tx excessive retries:0 Invalid misc:0 Missed beacon:0
Tags: ,

Data Back-up Bash Script

Data Back-up Requirement

Last year (2008), when getting processes in place for our new web and software development business, getpepper, I put together an all important data backup procedure. My aim was, in the worse case, to ensure that we could restore all but the last few days-worth of data for our own systems and that of our clients.

We mostly use open source systems and tools to create and manage our websites and write our software, with the Ubuntu Linux distribution forming the platform upon which our server-based systems (source control (Subversion), issue tracking (Trac), CRM, etc.) and some of our desktop systems run.

After some research on Linux-based back-up facilities I settled on using a Bash shell script that would allow us to run a regular back-up cycle using external portable hard disks. The weekly back-up shell script, which saves to USB hard drives, is based upon a script provided by Mike Rubel.

The Script

The script uses the rsync tool to provide the incremental functionality of the back-up. Here’s the adapted script that we use.

# ============================
# Author: Paul Pepper (though see description below for credits)
# Created: 6 November 2008
# Description:
# Rotating-snapshot utility adapted from Mike Rubel's make_snapshop.sh which
# can be found at http://www.mikerubel.org/computers/rsync_snapshots/
# Basically, this script performs rotating backup-snapshots of /home whenever
# it is called.
# ============================

#!/bin/bash

unset PATH # suggestion from H. Milz: avoid accidental use of $PATH

# ============================
# System commands used by this script
# ============================
ID=/usr/bin/id
ECHO=/bin/echo

MOUNT=/bin/mount
UMOUNT=/bin/umount
RM=/bin/rm
MV=/bin/mv
CP=/bin/cp
TOUCH=/bin/touch
RSYNC=/usr/bin/rsync

# ============================
# File names and locations
# ============================

MOUNT_DEVICE=/dev/sdb1
MOUNT_POINT=/media/sdb
BACKUP_TO_DIR=/backup/
BACKUP_FROM_DIR=/home
SNAPSHOT=snapshot
EXCLUDES=
BACKUP_TO_PATH=${MOUNT_POINT}/${BACKUP_TO_DIR}/${SNAPSHOT}

# ============================
# The script
# ============================

# Make sure we're running as root
if [ `$ID -u` != '0' ]; then
    $ECHO "$0 must be executed as root. Exiting!"
    exit 1
fi

# Attempt to mount the backup device, else abort
$MOUNT -o rw $MOUNT_DEVICE $MOUNT_POINT
if [ $? -ne 0 ]; then
    $ECHO "$0: Could not mount $MOUNT_DEVICE on $MOUNT_POINT as readwrite"
    exit 1
fi

# Step 1: delete the oldest snapshot, if it exists:
if [ -d ${BACKUP_TO_PATH}.3 ] ; then
    $RM -rf ${BACKUP_TO_PATH}.3
fi

# Step 2: shift the middle snapshots(s) back by one, if they exist
if [ -d ${BACKUP_TO_PATH}.2 ] ; then
    $MV ${BACKUP_TO_PATH}.2 \
    ${BACKUP_TO_PATH}.3
fi

if [ -d ${BACKUP_TO_PATH}.1 ] ; then
    $MV ${BACKUP_TO_PATH}.1 \
    ${BACKUP_TO_PATH}.2
fi

# Step 3: make a hard-link-only (except for dirs) copy of the latest snapshot,
# if that exists
if [ -d ${BACKUP_TO_PATH}.0 ] ; then
    $CP -al ${BACKUP_TO_PATH}.0 \
    ${BACKUP_TO_PATH}.1
fi

# Step 4: rsync from the system into the latest snapshot (notice that
# rsync behaves like cp --remove-destination by default, so the destination
# is unlinked first. If it were not so, this would copy over the other
# snapshot(s) too!
$RSYNC -va --delete --delete-excluded \
    --exclude-from="$EXCLUDES" \
       ${BACKUP_FROM_DIR} ${BACKUP_TO_PATH}.0

# Step 5: update the mtime of our most recent snapshot.
$TOUCH ${BACKUP_TO_PATH}.0

# Unmount the device to which we've written the backup
${UMOUNT} ${MOUNT_POINT}
if [ $? -ne 0 ]; then
    $ECHO "$0: Could not unmount ${MOUNT_POINT}"
    exit 1
fi

Here’s an outline of our weekly back-up process:

1. Grab one of the external hard disks.

2. Attach hard disk to server via a USB connector.

3. Log in to server as a regular user – don’t _su_ to root!

4. Run the back-up shell script:

$ sudo ./backup-snapshot.sh

5. Disconnect hard disk and return to its place of safekeeping!

And that’s it!

All users who perform the back-up must have the necessary permissions to run the shell. I enforce this by adding those users as sudoers, only permitting privileged access to the back-up shell script. Here’s the relevant parts of the sudoers file that grants that access – note that it is recommended that you use visudo when editing this file.

# User alias specification
User_Alias BACKUP_USERS = ann, bill

# Cmnd alias specification
Cmnd_Alias BACKUP_CMND = /somepath/backup-snapshot.sh, /bin/mount, /bin/umount, /bin/touch, /usr/bin/rsync

# Permit BACKUP_USERS to run the back-up script as root from all locations
BACKUP_USERS ALL=(root) BACKUP_CMND