<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Aaron Toponce &#187; Linux</title>
	<atom:link href="http://pthree.org/category/linux/feed/" rel="self" type="application/rss+xml" />
	<link>http://pthree.org</link>
	<description>Linux.  GNU.  Freedom.</description>
	<lastBuildDate>Sun, 06 May 2012 14:41:18 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4-beta2-20489</generator>
		<item>
		<title>Zombie Proccess- What They Are and How To Handle Them</title>
		<link>http://pthree.org/2012/04/27/zombie-proccess-what-they-are-and-how-to-handle-them/</link>
		<comments>http://pthree.org/2012/04/27/zombie-proccess-what-they-are-and-how-to-handle-them/#comments</comments>
		<pubDate>Fri, 27 Apr 2012 20:07:04 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=2381</guid>
		<description><![CDATA[First off, a zombie process isn&#8217;t really a process. At least it&#8217;s not executing anymore. A zombie process is more of a &#8220;state&#8221;, and that state is &#8220;defunct&#8221;. However, we typically refer to them as &#8220;zombie processes&#8221;, so I&#8217;ll stick with convention here. Second, a zombie process on a Unix system is a child process [...]]]></description>
			<content:encoded><![CDATA[<p>First off, a zombie process isn&#8217;t really a process. At least it&#8217;s not executing anymore. A zombie process is more of a &#8220;state&#8221;, and that state is &#8220;defunct&#8221;. However, we typically refer to them as &#8220;zombie processes&#8221;, so I&#8217;ll stick with convention here. Second, a zombie process on a Unix system is a child process that has not been waited on by the parent. In a typical scenario, when a child process is finished executing its task, the chain of events will go something like this:</p>
<ol>
<li>Child process issues the signal SIGCHLD to the parent.</li>
<li>Parent receives SIGCHLD, issues the &#8220;wait()&#8221; system call.</li>
<li>Parent now receives the exit code of the child.</li>
<li>Parent reaps the child from the process table.</li>
</ol>
<p>So, when the child process has finished execution of its task, it will report the exit code to the parent. At this point, the child process will remain in the process table until it receives further instruction from the parent. This wait is the defunct, or zombie state. So, in reality, child processes are in this state all the time. It&#8217;s just that normally, the parent process acts on it immediately. When the parent does not respond, then we have the zombie state of that child process.</p>
<p>You can check if there are any zombie processes on your system with the following command:</p>
<pre>$ ps -eo pid,ppid,user,args,stat --sort stat</pre>
<p>Any state of &#8220;Z&#8221; is a zombie state. So, the question becomes, how do you clean out the zombie, if it is causing issues with your system? Well, you have 3 options:</p>
<ol>
<li>Physically wait around. Sometimes, the parent is busy, and just hasn&#8217;t acknowledged the child. When the parent is free, it could clean it up.</li>
<li>Send the &#8220;SIGCHLD&#8221; signal to the parent process. The above command will give you that output in the &#8220;PPID&#8221; column.</li>
<li>Fully kill the parent process. Any child processes will be orphaned, and picked up by INIT. INIT does frequent reaping of child processes and will reap any zombie states.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2012/04/27/zombie-proccess-what-they-are-and-how-to-handle-them/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Install ZFS on Debian GNU/Linux</title>
		<link>http://pthree.org/2012/04/17/install-zfs-on-debian-gnulinux/</link>
		<comments>http://pthree.org/2012/04/17/install-zfs-on-debian-gnulinux/#comments</comments>
		<pubDate>Tue, 17 Apr 2012 20:10:40 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Debian]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=2357</guid>
		<description><![CDATA[UPDATE (May 06, 2012): I apologize for mentioning it supports encryption. Pool version 28 is the latest source that the Free Software community has. Encryption was not added until pool version 30. So, encryption is not supported natively with the ZFS on Linux project. However, you can use LUKS containers underneath, or you can use [...]]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE (May 06, 2012)</strong>: I apologize for mentioning it supports encryption. Pool version 28 is the latest source that the Free Software community has. Encryption was not added until pool version 30. So, encryption is not supported natively with the ZFS on Linux project. However, you can use LUKS containers underneath, or you can use Ecryptfs for the entire filesystem, which would still give you all the checksum, scrubbing and data integrity benefits of ZFS. Until Oracle gets their act together, and releases the current sources of ZFS, crypto is not implemented.</p>
<p>Quick post on installing ZFS as a kernel module, not FUSE, on Debian GNU/Linux. The documents already exist for getting this going, I&#8217;m just hoping to spread this to a larger audience, in case you are unaware that it exists.</p>
<p>First, the <a href="https://www.llnl.gov/">Lawrence Livermore National Laboratory</a> has been working on porting the native Solaris ZFS source to the Linux kernel as a kernel module. So long as the project remains under contract by the Department of Defense in the United States, I&#8217;m confident there will be continuous updates. You can track the progress of that porting at <a href="http://zfsonlinux.org">http://zfsonlinux.org</a>.</p>
<p>Now, download the SPL and ZFS sources. I&#8217;m running the latest RC, which seems to be quite stable:</p>
<pre>$ mkdir ~/src/{spl,zfs}
$ cd ~/src/spl
$ wget http://github.com/downloads/zfsonlinux/spl/spl-0.6.0-rc8.tar.gz
$ cd ~/src/zfs
$ wget http://github.com/downloads/zfsonlinux/zfs/zfs-0.6.0-rc8.tar.gz</pre>
<p>At this point, you will need to install the dependencies for SPL, then go ahead and compile and make the necessary .deb files:</p>
<pre>$ sudo aptitude install build-essential gawk alien fakeroot linux-headers-$(uname -r)
$ cd ~/src/spl
$ tar -xf spl-0.6.0-rc8.tar.gz
$ cd spl-0.6.0-rc8
$ ./configure
$ make deb
$ sudo dpkg -i *.deb</pre>
<p>Now do the same for ZFS:</p>
<pre>$ sudo aptitude install zlib1g-dev uuid-dev libblkid-dev libselinux-dev parted lsscsi
$ cd ~/src/zfs
$ tar -xf zfs-0.6.0-rc8.tar.gz
$ cd zfs-0.6.0-rc8
$ ./configure
$ make deb
$ sudo dpkg -i *.deb</pre>
<p>If you&#8217;re running Ubuntu, which I know most of you are, you can install the packages from the Launchpad PPA <a href="https://launchpad.net/~zfs-native">https://launchpad.net/~zfs-native</a>.</p>
<p><strong>A word of note:</strong> the manpages get installed to /share/man/. I found this troubling. You can modify your $MANPATH variable to include /share/man/man8/, or by creating symlinks, which is the approach I took:</p>
<pre># cd /usr/share/man/man8/
# ln -s /share/man/man8/zdb.8 zdb.8
# ln -s /share/man/man8/zfs.8 zfs.8
# ln -s /share/man/man8/zpool.8 zpool.8</pre>
<p>Now, make your zpool, and start playing:</p>
<pre>$ sudo zpool create test raidz sdd sde sdf sdg sdh sdi</pre>
<p>It is stable enough to run a ZFS root filesystem on a GNU/Linux installation for your workstation as something to play around with. It is copy-on-write, supports compression, deduplication, file atomicity, off-disk caching, <del datetime="2012-05-06T14:32:22+00:00">encryption,</del> and much more. At this point, unfortunately, I&#8217;m convinced that ZFS as a Linux kernel module will become &#8220;stable&#8221; long before Btrfs will be stable in the mainline kernel. Either way, it doesn&#8217;t matter to me. Both are Free Software, and both provide the long needed features we&#8217;ve needed with today&#8217;s storage needs. Competition is healthy, and I love having choice. Right now, that choice might just be ZFS.</p>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2012/04/17/install-zfs-on-debian-gnulinux/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Mount Raw Images</title>
		<link>http://pthree.org/2012/04/16/mount-raw-images/</link>
		<comments>http://pthree.org/2012/04/16/mount-raw-images/#comments</comments>
		<pubDate>Mon, 16 Apr 2012 20:39:12 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=2351</guid>
		<description><![CDATA[Just recently, I needed to mount a KVM raw image file, because it was depending on a network mount that was no longer accessible, and any attempts to interact with the boot process failed. So, rather than booting off a live CD, or some other medium, I decided to mount the raw image file. After [...]]]></description>
			<content:encoded><![CDATA[<p>Just recently, I needed to mount a KVM raw image file, because it was depending on a network mount that was no longer accessible, and any attempts to interact with the boot process failed. So, rather than booting off a live CD, or some other medium, I decided to mount the raw image file. After all, it is ext4.</p>
<p>However, mounting an image file means knowing where the root filesystem begins, which means knowing how to offset the mount, so you can access your data correctly. I used the following:</p>
<p>First, I setup a loop back device, so I could gather information about its partition setup:</p>
<pre># losetup /dev/loop0 virt01.img
# fdisk -l /dev/loop0

Disk /dev/loop0: 21.5 GB, 21474836480 bytes
255 heads, 63 sectors/track, 2610 cylinders, total 41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0009bdb7

      Device Boot      Start         End      Blocks   Id  System
/dev/loop0p1        37943296    41940991     1998848   82  Linux swap / Solaris
/dev/loop0p2   *        2048    37943295    18970624   83  Linux

Partition table entries are not in disk order</pre>
<p>In this case, the virtual machine filesystem is 21.5 GB in size, in reads and writes in 512 byte blocks. Further, it appears as though swap occupies the second partition, while the ext4 root filesystem occupies the first, and begins at sector 2048, or byte 2048*512=1048576.</p>
<p>So, now I just need to tear down the loop back device, and create it again with an offset of 1048576 bytes, at which point, I should be able to mount the device:</p>
<pre># losetup -d /dev/loop0
# losetup /dev/loop0 virt01.img -o 1048576
# mount /dev/loop0 /mnt
# ls /mnt
bin/   home/            lib32/       mnt/   run/      sys/  vmlinuz@
boot/  initrd.img@      lib64/       opt/   sbin/     tmp/  vmlinuz.old@
dev/   initrd.img.old@  lost+found/  proc/  selinux/  usr/
etc/   lib/             media/       root/  srv/      var/</pre>
<p>At this point, I can edit my problematic /mnt/etc/fstab file to fix the troubled boot, and boot it up.</p>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2012/04/16/mount-raw-images/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Setup Network Interfaces in Debian</title>
		<link>http://pthree.org/2012/02/26/setup-network-interfaces-in-debian/</link>
		<comments>http://pthree.org/2012/02/26/setup-network-interfaces-in-debian/#comments</comments>
		<pubDate>Mon, 27 Feb 2012 02:57:23 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Debian]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=2321</guid>
		<description><![CDATA[If you&#8217;re not using NetworkManager or Wicd, or some other similar tool to automatically manage your network interfaces for you, this post is for you. In the Debian world, you have a single file that manages your network interfaces. It can manage VLANs, bonded interfaces, virtual interfaces and more. You can establish rules on what [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re not using NetworkManager or Wicd, or some other similar tool to automatically manage your network interfaces for you, this post is for you. In the Debian world, you have a single file that manages your network interfaces. It can manage VLANs, bonded interfaces, virtual interfaces and more. You can establish rules on what the interface should do before brought online, what it can do while online, and what it can do after online. These same rules could be applied for taking the interface down as well. Let&#8217;s look at some of these.</p>
<p>First, let&#8217;s look at the basic setup for getting an interface online with DHCP. The file we&#8217;ll be looking at this entire time is the /etc/network/interfaces file:</p>
<pre>auto eth0
allow-hotplug eth0
iface eth0 inet dhcp</pre>
<p>The first line tells the kernel to bring the &#8220;eth0&#8243; interface up when the system boots. The second line tells the kernel to start the interface if a &#8220;hotplug&#8221; event is triggered. The third line defines the configuration of the &#8220;eth0&#8243; interface. In this case, it should use IPv4, and should request an IP address from a DHCP server. A static configuration could look like this:</p>
<pre>auto eth0
allow-hotplug eth0
iface eth0 inet static
    address 10.19.84.2
    network 10.19.84.0
    gateway 10.19.84.1
    netmask 255.255.255.0</pre>
<p>The first two lines remain the same. In the third line, we have decided to use static addressing, rather than dynamic. Then, we followed through by configuring the interface. It&#8217;s important to note that the indentation is not required. I only indented it for my benefit.</p>
<p>What about bonding? Simple enough. Suppose you have 2 NICs, one on the motherboard, and other in a PCI slot, and you want to ensure high availability, should the PCI card die. Then you could do something like this:</p>
<pre>auto eth0
iface eth0 inet manual
    post-up ifconfig $IFACE up
    pre-down ifconfig $IFACE down

auto eth1
iface eth1 inet manual
    post-up ifconfig $IFACE up
    pre-down ifconfig $IFACE down

auto bond0
iface bond0 inet static
    bond-slaves eth0 eth1
    # LACP configuration
    bond_mode 802.3ad
    bond_miimon 100
    bond_lcap_rate faste
    bond_xmit_hash_policy layer2+3
    address 10.19.84.2
    network 10.19.84.0
    gateway 10.19.84.1
    netmask 255.255.255.0</pre>
<p>Technically, I don&#8217;t need to tell the kernel to bring up interfaces eth0 and eth1, if I tell the kernel to bring up bond0, and slave the eth0 and eth1 interfaces. But, this configuration illustrates some points. First, there are the pre-up, up, post-up, pre-down, down, and post-down commands that you can use in your network interfaces(5) file. Each does something to the interface at different times during the configuration. Also notice I&#8217;m using the $IFACE variable. There are others that exist, that allow you to create scripts for your interfaces. See <a href="http://www.debian.org/doc/manuals/debian-reference/ch05.en.html#_scripting_with_the_ifupdown_system">http://www.debian.org/doc/manuals/debian-reference/ch05.en.html#_scripting_with_the_ifupdown_system</a> for more information.</p>
<p>On the bonded interface, I&#8217;m putting in two slaves, then setting some bonding configuration that I want, such as using 802.3ad mode. Of course, the interface is static, so I provided the necessary information.</p>
<p>What if we wanted to add our bonded interface to a VLAN? Simple. Just append a dot &#8220;.&#8221; and the VLAN number you want the interface in. Like so:</p>
<pre>auto bond0
iface bond0 inet manual
    bond-slaves eth0 eth1
    # LACP configuration
    bond_mode 802.3ad
    bond_miimon 100
    bond_lcap_rate faste
    bond_xmit_hash_policy layer2+3

auto bond0.42
iface bond0.42 inet static
    address 10.19.84.2
    network 10.19.84.0
    gateway 10.19.84.1
    netmask 255.255.255.0
    # necessary due to a bonding bug in vlan tools
    vlan-raw-device bond0</pre>
<p>Bring the interface up, the verify that the kernel has assigned it to the right VLAN:</p>
<pre>$ sudo cat /proc/net/vlan/config
VLAN Dev name    | VLAN ID
Name-Type: VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD
bond0.42        | 42  | bond0</pre>
<p>Notice that I specified &#8220;vlan-raw-device bond0&#8243;. This is due to a bonding bug in the VLAN tools, where merely specifying which VLAN the interface should be in by its name is not enough. You must also tell the kernel the bonded interface that the VLAN interface should be in.</p>
<p>How about bridged devices:</p>
<pre>auto bond0
iface bond0 inet manual
    bond-slaves eth0 eth1
    # LACP configuration
    bond_mode 802.3ad
    bond_miimon 100
    bond_lcap_rate faste
    bond_xmit_hash_policy layer2+3

auto bond0.42
iface bond0.42 inet manual
    post-up ifconfig $IFACE up
    pre-down ifconfig $IFACE down
    # necessary due to a bonding bug in vlan tools
    vlan-raw-device bond0

auto br42
iface br42 inet static
    bridge_ports bond0.42
    address 10.19.84.1
    netmask 255.255.255.0
    network 10.19.84.0
    gateway 10.19.84.1</pre>
<p>The only new thing here is the &#8220;bridge_ports&#8221; command. In this case, our bridged device is bridging our bond0.42 interface, which is in VLAN 42. Imagine having a KVM or Xen hypervisor that has a guest that needs to be in several VLANs. How would you setup all those bridges? Simple. Just create a VLAN interface for each VLAN, then create a bridge for each bonded interface in that VLAN.</p>
<p>Lastly, what about virtual IPs? I&#8217;ve heard that you can assign multiple IP addresses to a single NIC. How do you set that up? Simple. Just add a colon &#8220;:&#8221; the append a unique number. For example, say I have only one NIC, but wish to have 2 IP addresses, each in different networks:</p>
<pre>auto eth0
iface eth0 inet static
    address 10.19.84.2
    netmask 255.255.255.0
    network 10.19.84.0
    gateway 10.19.84.1

auto eth0:1
iface eth0:1 inet static
    address 10.13.37.2
    netmask 255.255.255.0
    network 10.13.37.0</pre>
<p>It&#8217;s important to note that you generally only need one default gateway to get out. Your kernel will route packets accordingly. If you must specify multiple gateways, then you must manually make edits to the kernel&#8217;s routing table, if everything isn&#8217;t setup correctly.</p>
<p>Of course, we could combine everything we learned here. See if you can make out what each interface is doing:</p>
<pre>auto eth0
iface eth0 inet manual
    pre-up ifconfig $IFACE up
    post-down ifconfig $IFACE down

auto eth1
iface eth1 inet manual
    pre-up ifcanfig $IFACE up
    post-down ifconfig $IFACe down

auto bond0
iface bond0 inet manual
    bond-slaves eth0 eth1 eth2 eth3
    # LACP configuration
    bond_mode 802.3ad
    bond_miimon 100
    bond_lacp_rate faste
    bond_xmit_hash_policy layer2+3

auto bond0.42
iface bond0.42 inet static
    address 10.19.84.2
    netmask 255.255.255.0
    netwark 10.19.84.0
    gateway 10.19.84.1
    # necessary due to a bonding up in vlan tools
    vlan-raw-device bond0

auto bond0.42:1
iface bond0.42:1 inet manual
    pre-up ifconfig $IFACE up
    post-down ifconfig $IFACE down
    # necessary due to a bonding bug in vlan tools
    vlan-raw-device bond0

auto br42
iface br42 inet static
    bridge_ports bond0.42:1
    address 10.13.37.2
    netmask 255.255.255.0
    network 10.13.37.0</pre>
<p>Lastly, MTU. There is a lot of misinformation out there about frame size. In my professional experience, setting the MTU to 9000 bytes does not result in improved performance. Not noticeably at least. But it does have an effect on the CPU. Setting a larger frame size can result in much lower CPU usage, both on the switch, and in your box. However, some protocols, such as UDP, might break with a 9k MTU. So, use appropriately. At any event, here is how I generally set my MTU when dealing with multiple interfaces:</p>
<pre>auto eth0
iface eth0 inet manual
    pre-up ifconfig $IFACE up
    post-down ifconfig $IFACE down
    mtu 9000

auto eth1
iface eth1 inet manual
    pre-up ifcanfig $IFACE up
    post-down ifconfig $IFACe down
    mtu 9000

auto bond0
iface bond0 inet manual
    bond-slaves eth0 eth1
    # LACP configuration
    bond_mode 802.3ad
    bond_miimon 100
    bond_lacp_rate faste
    bond_xmit_hash_policy layer2+3
    mtu 9000

auto bond0.42
iface bond0.42 inet static
    address 10.19.84.2
    netmask 255.255.255.0
    network 10.19.84.0
    gateway 10.19.84.1
    mtu 9000
    # necessary due to a bug in vlan tools
    vlan-raw-device bond0

auto bond0.43
iface bond0.43 inet static
    address 10.13.37.2
    netmask 255.255.255.0
    network 10.13.37.0
    mtu 1500
    # necessary due to a bug in vlan tools
    vlan-raw-device bond0</pre>
<p>Note that I set the MTU to 9000 on all interfaces except for bond0.43, which is 1500. This is perfectly acceptable. In all reality, setting the MTU to 1500 on bond0.43 is just capping what bond0 can really do. But, it is important to set the MTU on each interface, otherwise the frame size of 1500 bytes will get set, and you&#8217;ll end up chopping up your packets anyway. You must also set the MTU to 9000 on the switch ports as well, and any other server and interfaces that you want jumbo frames on.</p>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2012/02/26/setup-network-interfaces-in-debian/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Note About Removing Files With find(1)</title>
		<link>http://pthree.org/2011/12/20/a-note-about-removing-files-with-find1/</link>
		<comments>http://pthree.org/2011/12/20/a-note-about-removing-files-with-find1/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 01:01:55 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=2149</guid>
		<description><![CDATA[I&#8217;ve seen on the internet, and elsewhere, that when there are too many arguments for rm(1) to handle, that the following command will suffice: % find /path -exec rm -rf {} \; While certainly functional, it&#8217;s not optimal. If there are thousands of files (as is often the case at my job), this command is [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve seen on the internet, and elsewhere, that when there are too many arguments for rm(1) to handle, that the following command will suffice:</p>
<pre>% find /path -exec rm -rf {} \;</pre>
<p>While certainly functional, it&#8217;s not optimal. If there are thousands of files (as is often the case at my job), this command is slow, slow, slow. The reason being are all the excessive fork() and exec() calls for each pass with rm(1). Instead, you could optimize find(1) by using &#8220;-delete&#8221;:</p>
<pre>% find /path -delete</pre>
<p>This is much more optimal, but it has one VERY nasty side effect. If you place &#8220;-delete&#8221; in the wrong spot in your find(1) command, you could delete all the files listed under &#8220;/path&#8221; before processing the necessary logic. From the find(1) manual:</p>
<blockquote><p><strong>Warnings:</strong> Don&#8217;t forget that the find command line is evaluated as an expression, so putting -delete first will make find try to delete everything below the starting points you specified. When testing a find line that you later intend to use with -delete, you should explicitly specify -depth in order to avoid later surprises. Because -delete implies -depth, you cannot usefully use -prune and -delete together.</p></blockquote>
<p>One nice benefit of &#8220;-delete&#8221;, however, is the proper handling of NUL characters in your filename, such as spaces, tabs or the newline character. Thankfully, there is another option, which is not only supported in GNU/Linux, but also in FreeBSD (and perhaps others):</p>
<pre>% find /path -print0 | xargs -0 rm -rf</pre>
<p>This avoids the excessive fork() and exec() system calls from our first command, and doesn&#8217;t have the nasty side effects of &#8220;-delete&#8221;. Further, because of &#8220;-print0&#8243; as a find(1) argument, and &#8220;-0&#8243; with xargs(1), we can handle files properly with NUL characters. Time the three commands above, and you&#8217;ll see that the last is most optimal.</p>
<p>We can squeeze some extra juice out of the command, though. All we need to do is cd(1) to the directory we wish to operate our find(1) command on:</p>
<pre>% cd /path &#038;&#038; find . -print0 | xargs -0 rm -rf</pre>
<p>Working with removing millions of files (yes, I do actually remove that many, often), I have found this latest find(1) command to be the most optimized in terms of sheer speed. It moves. You may find the same results as I.</p>
<p>FYI.</p>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2011/12/20/a-note-about-removing-files-with-find1/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Salt Packaged For Debian/Ubuntu</title>
		<link>http://pthree.org/2011/09/29/salt-packaged-for-debianubuntu/</link>
		<comments>http://pthree.org/2011/09/29/salt-packaged-for-debianubuntu/#comments</comments>
		<pubDate>Thu, 29 Sep 2011 15:04:33 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Debian]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=2073</guid>
		<description><![CDATA[I created a Debian package for Salt, doing my best to adhere to the Debian Policy. You can find it at http://mentors.debian.net/package/salt. If you&#8217;re not familiar with Salt, head over to http://saltstack.org and check it out. From the author&#8217;s website: Salt is a powerful remote execution manager that can be used to administer servers in [...]]]></description>
			<content:encoded><![CDATA[<p>I created a Debian package for Salt, doing my best to adhere to the <a href="http://www.debian.org/doc/debian-policy/">Debian Policy</a>. You can find it at <a href="http://mentors.debian.net/package/salt">http://mentors.debian.net/package/salt</a>. If you&#8217;re not familiar with Salt, head over to <a href="http://saltstack.org">http://saltstack.org</a> and check it out. From the author&#8217;s website:</p>
<blockquote><p>Salt is a powerful remote execution manager that can be used to administer servers in a fast and efficient way.</p>
<p>Salt allows commands to be executed across large groups of servers. This means systems can be easily managed, but data can also be easily gathered. Quick introspection into running systems becomes a reality.</p>
<p>Remote execution is usually used to set up a certain state on a remote system. Salt addresses this problem as well, the salt state system uses salt state files to define the state a server needs to be in.</p>
<p>Between the remote execution system, and state management Salt addresses the backbone of cloud and data center management.</p></blockquote>
<p>Think Puppet on steroids. And done correctly.</p>
<p>At any event, yes, I&#8217;m looking for a Debian Developer to sponsor me getting it into Debian proper. If you are an Ubuntu Developer, and could help sponsor me getting it into Ubuntu as well, that would be awesome!</p>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2011/09/29/salt-packaged-for-debianubuntu/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How To Properly Create And Burn CD/DVD ISO Images From The Command Line</title>
		<link>http://pthree.org/2011/09/26/how-to-properly-create-and-burn-cddvd-iso-images-from-the-command-line/</link>
		<comments>http://pthree.org/2011/09/26/how-to-properly-create-and-burn-cddvd-iso-images-from-the-command-line/#comments</comments>
		<pubDate>Tue, 27 Sep 2011 02:59:31 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Debian]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=2067</guid>
		<description><![CDATA[Too often, I see the recommendation on forums, IRC, and elsewhere across the internet to use improper tools for creating ISO images. For example, consider the following two commands, both of which are not the correct way to build a CD/DVD image: $ dd if=/dev/scd0 of=cdimage.iso # NO! Or worse yet: $ cat /dev/scd0 > [...]]]></description>
			<content:encoded><![CDATA[<p>Too often, I see the recommendation on forums, IRC, and elsewhere across the internet to use improper tools for creating ISO images. For example, consider the following two commands, both of which are not the correct way to build a CD/DVD image:</p>
<pre>$ dd if=/dev/scd0 of=cdimage.iso # NO!</pre>
<p>Or worse yet:</p>
<pre>$ cat /dev/scd0 > cdimage.iso # NO!</pre>
<p>As you are probably thinking, the problem with the two commands above, is that they provide no error checking while building the image. So, in order to make sure you have all the bits, you need to use another tool, such as using the MD5 hashing algorithm:</p>
<pre>$ md5sum /dev/scd0 cdimage.iso
d642d524dd2187834a418710001bbf82  /dev/cdrom
d642d524dd2187834a418710001bbf82  cdimage.iso</pre>
<p>Thankfully, the hashes above match. But, what if they didn&#8217;t? Then, you get to redo your dd(1) command (or, shudder, cat(1)) from above, and then rerun md5sum(1) to make sure you got all the bits. Doesn&#8217;t sound like much fun to me. Thankfully, there is a better way, one which handles the checksum while doing the copy.</p>
<p>You want to use readom(1) (&#8220;read optical media&#8221;) from the wodim(1) (&#8220;write optical disk media&#8221;) package. Consider the following command:</p>
<pre>$ readom dev=/dev/scd0 f=cdimage.iso # YES!</pre>
<p>If readom(1) fails to get the bits during the copy, it will let you know that it&#8217;s struggling. If it got all the bits, you know you have them all, because of the error checking during the copy. Sure will save you a lot of time running manual hashes when finished.</p>
<p>Now, what about burning a copy of the ISO image? Surely you use dd(1), yes? Something like:</p>
<pre>$ dd if=cdimage.iso of=/dev/scd0 # NO!</pre>
<p>NO! Instead, use wodim(1) directly:</p>
<pre>$ wodim -v -eject cdimage.iso # YES!</pre>
<p>For the same reasons that you want to use readom(1) for creating ISO images from CD/DVD, you want to use wodim(1) for burning ISO images to CD/DVD. What happens if after using dd(1) to create your CD/DVD, the md5sum(1) hash doesn&#8217;t line up with the image? You didn&#8217;t get all the bits, and created a coaster. Use wodim(1) and should it succeed, you can rest assured that you have all the bits.</p>
<p>So, remember, readom(1) and wodim(1) are the tools you want when creating and/or burning ISO images from the command line. Any other tool, and you&#8217;re likely doing it wrong.</p>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2011/09/26/how-to-properly-create-and-burn-cddvd-iso-images-from-the-command-line/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Avoid Using which(1)</title>
		<link>http://pthree.org/2011/09/26/avoid-using-which1/</link>
		<comments>http://pthree.org/2011/09/26/avoid-using-which1/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 11:30:40 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Debian]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=2054</guid>
		<description><![CDATA[This post comes from BashFAQ/081 on Greg&#8217;s Wiki. He argues why you should not be using which(1) to determine if a command is in your $PATH at the end of the page. I&#8217;ll put that argument at the front: The command which(1) (which is often a csh script, although sometimes a compiled binary) is not [...]]]></description>
			<content:encoded><![CDATA[<p>This post comes from <a href="http://mywiki.wooledge.org/BashFAQ/081">BashFAQ/081</a> on Greg&#8217;s Wiki. He argues why you <strong>should not</strong> be using which(1) to determine if a command is in your $PATH at the end of the page. I&#8217;ll put that argument at the front:</p>
<blockquote><p>The command which(1) (which is often a csh script, although sometimes a compiled binary) is <strong>not reliable</strong> for this purpose. which(1) may not set a useful exit code, and it may not even write errors to stderr. Therefore, in order to have a prayer of successfully using it, one must parse its output (wherever that output may be written).</p>
<p>Note that which(1)&#8217;s output when a command is not found is not consistent across platforms. On HP-UX 10.20, for example, it prints &#8220;no qwerty in /path /path /path &#8230;&#8221;; on OpenBSD 4.1, it prints &#8220;qwerty: Command not found.&#8221;; on Debian (3.1 through 5.0 at least) and SuSE, it prints nothing at all; on Red Hat 5.2, it prints &#8220;which: no qwerty in (/path:/path:&#8230;)&#8221;; on Red Hat 6.2, it writes the same message, but on standard error instead of standard output; and on Gentoo, it writes something on stderr.</p></blockquote>
<p>(Quotation and manpage reference additions mine). So, if which(1) is bad news, then what is the &#8220;proper&#8221; way to determine if a command is in your $PATH? Well POSIX has an answer, and not surprisingly, the command to use is &#8220;command&#8221;:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># POSIX</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">command</span> <span style="color: #660033;">-v</span> qwerty <span style="color: #000000; font-weight: bold;">&gt;/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> qwerty exists<br />
<span style="color: #000000; font-weight: bold;">else</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> qwerty does not exist<br />
<span style="color: #000000; font-weight: bold;">fi</span></div></td></tr></tbody></table></div>
<p>The &#8220;command&#8221; built-in also returns true for shell built-ins. If you absolutely must check only PATH, the only POSIX way is to iterate over it:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># POSIX</span><br />
IsInPath <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #7a0874; font-weight: bold;">&#40;</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$#</span> <span style="color: #660033;">-eq</span> <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #000000;">2</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #660033;">-f</span>; <span style="color: #007800;">IFS</span>=:<br />
&nbsp; <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #c20cb9; font-weight: bold;">dir</span> <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #007800;">$PATH</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$dir</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #007800;">dir</span>=. <span style="color: #666666; font-style: italic;"># Legacy behaviour</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-x</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$dir</span>/$1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">return</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">done</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #000000;">1</span><br />
<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">if</span> IsInPath qwerty; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> qwerty exists<br />
<span style="color: #000000; font-weight: bold;">else</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> qwerty does not exist<br />
<span style="color: #000000; font-weight: bold;">fi</span></div></td></tr></tbody></table></div>
<p>There are also Bash built-ins that can be used, should you have Bash installed on your system:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># Bash using the 'hash' built-in</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">hash</span> qwerty <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> qwerty exists<br />
<span style="color: #000000; font-weight: bold;">else</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> qwerty does not exist<br />
<span style="color: #000000; font-weight: bold;">fi</span></div></td></tr></tbody></table></div>
<p>Or:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># Bash using the 'type' built-in</span><br />
<span style="color: #666666; font-style: italic;"># type -P forces a PATH search, skipping builtins and so on</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">type</span> <span style="color: #660033;">-P</span> qwerty <span style="color: #000000; font-weight: bold;">&gt;/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> qwerty exists<br />
<span style="color: #000000; font-weight: bold;">else</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> qwerty does not exist<br />
<span style="color: #000000; font-weight: bold;">fi</span></div></td></tr></tbody></table></div>
<p>If you prefer the ZSH (my addition not present in the wiki), as I do, then you can look in the $commands associative array:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># ZSH using the $commands associative array</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$commands</span><span style="color: #7a0874; font-weight: bold;">&#91;</span>qwerty<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&gt;/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> qwerty exists<br />
<span style="color: #000000; font-weight: bold;">else</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> qwerty does not exist<br />
<span style="color: #000000; font-weight: bold;">fi</span></div></td></tr></tbody></table></div>
<p>I like that at the end of the FAQ, he gives a shell script for using which(1) should it be absolutely necessary. Not only do you have to test for exit code, but you also have to test for common strings in the output, seeing as though which(1) doesn&#8217;t always use exit codes properly:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># Bourne. &nbsp;Last resort -- using which(1)</span><br />
<span style="color: #007800;">tmpval</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #007800;">LC_ALL</span>=C <span style="color: #c20cb9; font-weight: bold;">which</span> qwerty <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span><span style="color: #000000; font-weight: bold;">`</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #007800;">$rc</span> <span style="color: #660033;">-ne</span> <span style="color: #000000;">0</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; <span style="color: #666666; font-style: italic;"># FOR NOW, we'll assume that if this machine's which(1) sets a nonzero</span><br />
&nbsp; <span style="color: #666666; font-style: italic;"># exit status, that it actually failed. &nbsp;I've yet to see any case where</span><br />
&nbsp; <span style="color: #666666; font-style: italic;"># which(1) sets an erroneous failure -- just erroneous &quot;successes&quot;.</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;qwerty is not installed. &nbsp;Please install it.&quot;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">else</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># which returned 0, but that doesn't mean it succeeded. &nbsp;Look for known error strings.</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$tmpval</span>&quot;</span> <span style="color: #000000; font-weight: bold;">in</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span>no\ <span style="color: #000000; font-weight: bold;">*</span>\ <span style="color: #000000; font-weight: bold;">in</span>\ <span style="color: #000000; font-weight: bold;">*|*</span>not\ found<span style="color: #000000; font-weight: bold;">*|</span><span style="color: #ff0000;">''</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;qwerty is not installed. &nbsp;Please install it.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Congratulations -- it seems you have qwerty (in <span style="color: #007800;">$tmpval</span>).&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">esac</span><br />
<span style="color: #000000; font-weight: bold;">fi</span></div></td></tr></tbody></table></div>
<p><strong>CONCLUSION:</strong><br />
You have many options to find whether or not a command exists in your $PATH, some POSIX, some proper built-ins. Regardless, you should be able to build platform-independent scripts using the proper tools, and using which(1) is not the right tool for the job. Hopefully, this has convinced you of that.</p>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2011/09/26/avoid-using-which1/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Use Your SSH Client To Help Prevent Stupid Mistakes</title>
		<link>http://pthree.org/2011/09/06/use-your-ssh-client-to-help-prevent-stupid-mistakes/</link>
		<comments>http://pthree.org/2011/09/06/use-your-ssh-client-to-help-prevent-stupid-mistakes/#comments</comments>
		<pubDate>Tue, 06 Sep 2011 15:12:37 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=2007</guid>
		<description><![CDATA[I have chosen the path of system administration for my career. It&#8217;s been very rewarding, and I really love my job. However, there are times when I make stupid mistakes that cost others money. I&#8217;m sure we&#8217;ve all been there. It&#8217;s stressful, embarrassing and can really shake you up, if you mistake is bad enough. [...]]]></description>
			<content:encoded><![CDATA[<p>I have chosen the path of system administration for my career. It&#8217;s been very rewarding, and I really love my job. However, there are times when I make stupid mistakes that cost others money. I&#8217;m sure we&#8217;ve all been there. It&#8217;s stressful, embarrassing and can really shake you up, if you mistake is bad enough. Many times, this happens because you fat-fingered an IP address, hostname, or something else, and your SSH client takes you somewhere you shouldn&#8217;t be. If that&#8217;s the case, hopefully this post can help.</p>
<p>According to the <a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh_config&#038;sektion=5">ssh_config(5)</a> manual:</p>
<pre>     <strong>LocalCommand</strong>
             Specifies a command to execute on the local machine after suc‐
             cessfully connecting to the server.  The command string extends
             to the end of the line, and is executed with the user's shell.
             The following escape character substitutions will be performed:
             ‘%d’ (local user's home directory), ‘%h’ (remote host name), ‘%l’
             (local host name), ‘%n’ (host name as provided on the command
             line), ‘%p’ (remote port), ‘%r’ (remote user name) or ‘%u’ (local
             user name).

             The command is run synchronously and does not have access to the
             session of the ssh(1) that spawned it.  It should not be used for
             interactive commands.

             This directive is ignored unless PermitLocalCommand has been
             enabled.</pre>
<p>As mentioned, the used of LocalCommand executes a local command after successfully connecting to the server. I figured this would be a great way to print something to the terminal, letting me know whether or not my client just connected to a production machine, a QA machine, or a development machine.</p>
<p>I wanted to use colors, to make it obvious. I don&#8217;t want to make the same mistake twice, so I want it painfully clear what machine I just went to. As a result, if I go to a development or home machine, use green. If I enter a QA machine, use yellow. If I enter a production, or other serious machine I probably shouldn&#8217;t be on, use red. As a result, I can take advantage of the ANSI escape sequences for color. In case you forgot, here are the colors and modes:</p>
<blockquote><p><strong>Colors</strong><br />
\e[{attr1;&#8230;;{attrN}m</p>
<p><strong>Text attributes</strong><br />
0 Reset<br />
1 Bright<br />
2 Dim<br />
4 Underscore<br />
5 Blink<br />
7 Reverse<br />
8 Hidden</p>
<p><strong>Foreground Colors</strong><br />
30 Black<br />
31 Red<br />
32 Green<br />
33 Yellow<br />
34 Blue<br />
35 Magenta<br />
36 Cyan<br />
37 White</p>
<p><strong>Background Colors</strong><br />
40 Black<br />
41 Red<br />
42 Green<br />
43 Yellow<br />
44 Blue<br />
45 Magenta<br />
46 Cyan<br />
47 White</p></blockquote>
<p>So, if I were about to SSH to a production machine, I probably want to make it as obvious as possible. Thus, I could print to the terminal, in blinking, bold, red text &#8220;PRODUCTION&#8221;. I could use the following command:</p>
<pre>print "\e[1;5;31PRODUCTIONm\e[0;m"</pre>
<p>Notice that at the end of the sequence, I&#8217;m resetting the text attributes. This is because if you don&#8217;t do this, you will keep the text attributes in your terminal, and that may have an affect on how the text is displayed when in your remote SSH connection.</p>
<p>A possible ~/.ssh/config file could look like this:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Host development<br />
&nbsp; &nbsp; Hostname dev.domain.tld<br />
&nbsp; &nbsp; LocalCommand print &quot;\e[1;32mDevelopment\e[0;m&quot;<br />
&nbsp; &nbsp; PermitLocalCommand yes<br />
<br />
Host qa<br />
&nbsp; &nbsp; Hostname qa.domain.tld<br />
&nbsp; &nbsp; LocalCommand print &quot;\e[1;33mQuality Assurance\e[0;m&quot;<br />
&nbsp; &nbsp; PermitLocalCommand yes<br />
<br />
Host production<br />
&nbsp; &nbsp; Hostname prod.domain.tld<br />
&nbsp; &nbsp; LocalCommand print &quot;\e[1;5;32mPRODUCTION\e[0;m&quot;<br />
&nbsp; &nbsp; PermitLocalCommand yes</div></td></tr></tbody></table></div>
<p>Here is a screenshot in action (without the blink):</p>
<p><img src="http://pthree.org/wp-content/uploads/2011/09/localcommand.png" alt="" title="localcommand" width="300" height="91" class="aligncenter size-full wp-image-2011" /></p>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2011/09/06/use-your-ssh-client-to-help-prevent-stupid-mistakes/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>My Tmux Hardstatus Theme</title>
		<link>http://pthree.org/2011/08/31/my-tmux-hardstatus-theme/</link>
		<comments>http://pthree.org/2011/08/31/my-tmux-hardstatus-theme/#comments</comments>
		<pubDate>Wed, 31 Aug 2011 20:32:13 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[irssi]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=1992</guid>
		<description><![CDATA[Recently, I&#8217;ve made the switch from GNU Screen to Tmux for my remote terminal multiplexor. I still prefer GNU Screen for serial connections, however (something the Tmux developers don&#8217;t seem to think is important). So, when getting it setup, I wanted my hardstatus line to imitate my GNU Screen hardstatus line as closely as possible. [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, I&#8217;ve made the switch from GNU Screen to Tmux for my remote terminal multiplexor. I still prefer GNU Screen for serial connections, however (something the Tmux developers don&#8217;t seem to think is important). So, when getting it setup, I wanted my hardstatus line to imitate my GNU Screen hardstatus line as closely as possible. Well, I got it to that point, then took it even further to work with <a href="http://pthree.org/2010/01/12/more-88-madcows/">my custom Irssi</a> and <a href="http://pthree.org/2009/10/14/more-zsh-prompt-love/">ZSH themes</a> (I want everything to tie in nicely). The only thing left is getting Mutt in order, but that&#8217;s for another post.</p>
<p>At any event, here is the configuration for the theme:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># hardstatus line theme<br />
set-option -g status-fg white<br />
set-option -g status-bg default<br />
set-option -g status-justify centre<br />
set-option -g status-left-length 13<br />
set-option -g status-left '#[fg=green][ #[fg=black,bright]#h #[fg=green,nobright]][#[default]'<br />
set-option -g status-right-length 16<br />
set-option -g status-right '#[fg=green]][ #[fg=black,bright]%m/%d %H:%M #[fg=green,nobright]]#[fg=default]'<br />
set-window-option -g window-status-current-format '#[fg=red,bg=default]( #[fg=white,bright,bg=default]#I:#W#[fg=red,nobright,bg=default] )#[fg=default]'<br />
set-window-option -g window-status-alert-attr bold<br />
set-window-option -g window-status-alert-fg yellow<br />
set-window-option -g window-status-alert-bg default</div></td></tr></tbody></table></div>
<p>Obviously, this won&#8217;t look that great on a terminal with a white background (or really any color other than black). And here is the screenshot:</p>
<p><a href="http://pthree.org/wp-content/uploads/2011/08/tmux.png"><img src="http://pthree.org/wp-content/uploads/2011/08/tmux.png" alt="" title="tmux" width="572" height="21" class="aligncenter size-full wp-image-1993" /></a></p>
<p>As you can clearly see, the active window you&#8217;re under is bold white with red parentheses around the window name. The previous window you were in is marked with a dash &#8216;-&#8217; (by default). An alert in a terminal will change the text to bold yellow, so long as you&#8217;re not in that window (as you can see with the &#8220;mutt&#8221; window). It ties in nicely with the <a href="http://pthree.org/wp-content/uploads/2011/08/88_madcows.theme">88_madcows.theme</a> file for Irssi, and the ZSH theme I built.</p>
<p>I&#8217;m new to building Tmux hardstatus lines, so if there is something I should be doing differently, let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2011/08/31/my-tmux-hardstatus-theme/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>I Am Going To OLF</title>
		<link>http://pthree.org/2011/08/25/i-am-going-to-olf/</link>
		<comments>http://pthree.org/2011/08/25/i-am-going-to-olf/#comments</comments>
		<pubDate>Thu, 25 Aug 2011 13:28:58 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=1983</guid>
		<description><![CDATA[I will be attending the Ohio Linux Fest this September (in about two weeks) giving a talk on &#8220;Password Theory and Breaking Encrypted Filesystems&#8221;. The talk covers some theory on what exactly makes a &#8220;secure password&#8221;, including some mathematics, entropy, random number generators, shadowed passwords, salts, rainbow tables and cryptographic hashes. I end the talk [...]]]></description>
			<content:encoded><![CDATA[<p>I will be attending the <a href="http://ohiolinux.org">Ohio Linux Fest</a> this September (in about two weeks) giving a talk on &#8220;Password Theory and Breaking Encrypted Filesystems&#8221;. The talk covers some theory on what exactly makes a &#8220;secure password&#8221;, including some mathematics, entropy, random number generators, shadowed passwords, salts, rainbow tables and cryptographic hashes. I end the talk by showing how to break into an encrypted filesystem, regardless of the type of encryption, or the software used to encrypt the filesystem. It should be a good talk. When my slides are ready, I&#8217;ll make them available online.</p>
<p>If you have thought about attending, you should <a href="http://www.ohiolinux.org/register">register</a>. You can see my talk, if you sign up just for the enthusiast package. You can attend a sponsored lunch (and other things) if you upgrade.</p>
<p>Also, I&#8217;ll be hosting the <a href="http://www.ohiolinux.org/bofs">PGP keysigning party</a> at the conference as well (a follow-up post is coming). My key is in the &#8220;strong set&#8221;, so by me signing your key, I&#8217;ll also be bringing you into the strong set as well, if you&#8217;re currently not in it. It&#8217;s all about strengthening the Web of Trust.</p>
<p>At any event, see you at the fest!</p>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2011/08/25/i-am-going-to-olf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenSSH Best Practices</title>
		<link>http://pthree.org/2011/07/22/openssh-best-practice/</link>
		<comments>http://pthree.org/2011/07/22/openssh-best-practice/#comments</comments>
		<pubDate>Fri, 22 Jul 2011 07:46:54 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Cryptology]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=1930</guid>
		<description><![CDATA[This post comes from Matt Taggart, who put together a document about the best practices for using OpenSSH. A lot of the points brought up in that document rang the bells of common sense, and are so good, it&#8217;s worth blogging about in hopes that the points mentioned therein reach as many as possible. I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>This post comes from Matt Taggart, who put together a document about the <a href="http://lackof.org/taggart/hacking/ssh/">best practices for using OpenSSH</a>. A lot of the points brought up in that document rang the bells of common sense, and are so good, it&#8217;s worth blogging about in hopes that the points mentioned therein reach as many as possible. I&#8217;ve also added a couple extra points that I&#8217;ve learned with my experience using OpenSSH.</p>
<p>These are best practices from the client perspective, not the server. Many of these points you will have already been familiar with, but some of them not as much. If you sit down and think about what you are doing as a client when you SSH to a server, some of the implications mentioned here make sense.</p>
<p>Lastly, security is a big topic, and not something that can be flipped on and off with a switch. Security always starts with the user. Unfortunately, increasing your security could mean making usability more of a pain in the rear. However, as an OpenSSH client, I hope the techniques mentioned here won&#8217;t decrease your usability too bad, while greatly increasing your overall OpenSSH security. With that said, let&#8217;s get started.</p>
<p><strong>0. Use ECC first, then RSA, then DSA with maximum bit strength.</strong><br />
When generating your OpenSSH keys, you should be aware of the cryptographic algorithms of the OpenSSH server that you are accessing, and what you can and cannot use. As of OpenSSH version 5.7, <a href="http://pthree.org/2011/02/17/elliptic-curve-cryptography-in-openssh/">elliptic curve cryptography is a supported algorithm</a>. It is proving to be a very secure, robust and light crypto algorithm, but it also must be supported by both the client and the remote server. This means that both the client and the server must be relatively new installations of OpenSSH- something that RHEL 6 and earlier, Debian GNU/Linux Stable 6 and earlier, Ubuntu 10.10 and earlier, and likely many other stable releases from other GNU/Linux operating systems, do not support. When you can, use elliptic curve cryptography for your SSH keys.</p>
<p>If ECC is not available on either your client or server, then you should choose RSA as your key&#8217;s crypto. DSA suffers from a weakness, where if the host does not have a sufficiently strong pseudorandom number generator (PRNG), then the &#8220;random k&#8221; could become exposed from the public key, allowing the attacker to build the private key from the public. The PRNG supplied by GNU/Linux (the device file &#8220;/dev/urandom&#8221;) is sufficiently strong, providing good random data from entropy pools- thus, GNU/Linux generally doesn&#8217;t suffer from this problem. Other operating systems could.</p>
<p>A great demonstration of DSA&#8217;s weakness can be found in <a href="http://rdist.root.org/2010/11/19/dsa-requirements-for-random-k-value/">this excellent blog post</a>, where the author demonstrates how trivial it is to build the private key when the &#8220;random k value&#8221; is known. Fortunately, RSA does not suffer from this weakness, and also allows you to build larger keys than DSA.</p>
<p>If neither ECC nor RSA is supported by the client nor server, as is the case with some archaic proprietary SSH implementations, then DSA is your only option. Unfortunately, it is also the default for OpenSSH when generating a key. So, you should always get into the habit of passing the &#8220;-t [type]&#8221; switch when generating your keys.</p>
<p>In all 3 cases, where possible, you should choose the maximum bit strength that the algorithm allows. This will put a bit of strain on the client&#8217;s CPU, but it will also give you the greatest strength when authenticating on the wire. When generating your key, use the &#8220;-b [size]&#8221; switch to specify the bit strength.</p>
<p><strong>1. Use SSH keys and make your servers require them.</strong><br />
There are three reasons why you would want to use SSH keys:</p>
<ol>
<li>SSH keys with a passphrase provide two-factor authentication.</li>
<li>SSH passwords can be read in plain text on the remote server.</li>
<li>SSH keys aren&#8217;t subject to brute force dictionary attacks, like passwords.</li>
</ol>
<p>Let&#8217;s cover each in detail. First, two-factor authentication. SSH keys use public key cryptography. You are given a private and public key when generated. During generation, you are asked to provide a passphrase for the private key. DO NOT GIVE IT AN EMPTY PASSPHRASE! By providing a passphrase to your key, you have enabled the two-factor authentication- something you have (the key) and something you know (the passphrase). Using SSH keys can be troublesome, however. As a result, take advantage of the SSH agent for your system to cache the passphrase locally on your client. This will increase your usability by only entering your key passphrase once, and using the agent to login to other servers without providing the key passphrase again.</p>
<p>Second is reading the user password in plain text on the remote SSH server. You may not think this is possible, as everything in OpenSSH is encrypted, right? Wrong. The two Achilles Heel&#8217;s in the connection are the client and servers themselves, where the decryption is taking place. Other users, specifically those who have superuser access, can exploit this. To demonstrate this, make a connection to a server that you have superuser access on. Then, from the client initiate a connection that would require your server password, but don&#8217;t supply it. Go back to the server, and find the process of the connection, and run an strace on the PID. Go back to the client, and type in your password. Watch, very likely in horror, the password be displayed on your console.</p>
<p><a href="http://blog.josephhall.com/2009/12/fun-with-sshd-and-strace.html">Here is an excellent writeup</a> by Joseph Hall on this very issue. The problem lies in whether or not you trust those who have superuser access on the server. You should only trust them enough to do their job on the server, and nothing more. Just because they have superuser access on the server, doesn&#8217;t mean they can be trusted with your banking account information. Because people use the same passwords over and over across multiple accounts, it&#8217;s likely that the password sniffed out of the connection is the same password for their email account. Or bank.</p>
<p>Third, as should be obvious, SSH keys aren&#8217;t subject to brute force dictionary attacks like passwords are. If you control the SSH server, and require that SSH keys are the mode of authentication, then brute force attacks will be in vain, regardless how long they try. If you have a publicly facing SSH server, you&#8217;re likely aware of how hard your server gets hit from attackers all over the world. By forcing key authentication, all those attacks are in vain.</p>
<p><strong>2. Don&#8217;t use a blank passphrase on your keys.</strong><br />
This should come as no surprise, but needs to be mentioned. Your SSH keys are something that should be guarded carefully, with sufficient paranoia. If for any reason, your SSH client is compromised, your SSH keys are a way in to the remote servers that you have access to. If your keys are not protected by passphrases, then after scouring your shell history, or SSH config for hosts to connect to, they&#8217;re in the SSH server with little effort. You must protect your keys with strong passphrases!</p>
<p>Now, I understand that there are some like me, who use SSH as the connection for nightly local backups, at which point the client will be asked for the passphrase of the SSH key. Because you wish this to be an automated process, and likely when you&#8217;re in bed, you won&#8217;t be available all the time to provide the credentials. So, you create an SSH keypair that is not passphrase protected. In such a scenario, here is what I would do:</p>
<ol>
<li>Only install this key on the backup SSH server, and no where else.</li>
<li>Do not install this key into an account that has superuser access.</li>
<li>Do not install this key into the superuser account.</li>
<li>On the backup server, change the key entry in the authorized_keys file to only allow connections from that client using that key (documented how below).</li>
</ol>
<p>The first, second and third points are easy enough to configure, but how do you configure the fourth point, and is it even possible? When you copy the key to the authorized_keys file on the SSH server, it could look something like this:</p>
<pre>ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzoblHIUARNP5Kq12QwUqxB6T7m8TWti4LIFcvOCa...</pre>
<p>Change the beginning of that entry to this:</p>
<pre>from="10.19.84.10",command="/home/user/bin/validate.sh" ssh-rsa AAAAB3NzaC1y...</pre>
<p>This tells the server that the only connections allowed to use this key can come from &#8220;10.19.84.10&#8243;, and when the connection is made, a local script is ran called &#8220;validate.sh&#8221;. Here are the contents of that script for me:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#!/bin/sh</span><br />
<br />
<span style="color: #000000; font-weight: bold;">case</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$SSH_ORIGINAL_COMMAND</span>&quot;</span> <span style="color: #000000; font-weight: bold;">in</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span>\<span style="color: #000000; font-weight: bold;">&amp;*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Rejected&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span>\<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Rejected&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span>\<span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Rejected&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span>\;<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Rejected&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span>\<span style="color: #000000; font-weight: bold;">&lt;*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Rejected&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span>\<span style="color: #000000; font-weight: bold;">`*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Rejected&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span>\<span style="color: #000000; font-weight: bold;">|*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Rejected&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; rsync\ --server<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">$SSH_ORIGINAL_COMMAND</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Rejected&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
<span style="color: #000000; font-weight: bold;">esac</span></div></td></tr></tbody></table></div>
<p>Make sure the script is executable by the user account on the SSH server, and test it before committing to it as part of your backup policy. If the client host is behind a dynamic IP address, or some other variable that prevents it from having a static address, you can remove the &#8220;from=&#8221; part, but leave the &#8220;command=&#8221; part. The goal is to minimize damage that can be done with that key.</p>
<p>Again, this is all if you need to perform an automated backup with SSH keys, where a passphrase cannot be performed. In almost every other case, your SSH key should be protected by a good, strong, <a href="http://pthree.org/2011/03/07/strong-passwords-need-entropy/">loaded with entropy</a> passphrase. Using one from a <a href="http://pthree.org/2010/09/21/password-cards/">passwordcard</a> is probably best.</p>
<p><strong>3. Use a separate key for every client you SSH from.</strong><br />
I admit that when I first started using SSH, this didn&#8217;t make much sense to me. The amount of keys that I generated was a lot, and managing them became somewhat of a pain. Then, when becoming system administrator of a large organization, and controlling upwards of 300 servers, managing that many keys become immensely intense.</p>
<p>I soon came to the realization that it wasn&#8217;t that big of a deal. It is trivial to copy the key to the remote host (this can be done with the &#8220;<a href="http://linux.die.net/man/1/ssh-copy-id">ssh-copy-id(1)</a>&#8221; command). Further, for work SSH keys, while I am in charge of managing those keys, I should only worry about work keys at work, and home keys at home. In other words, separate the management of the keys.</p>
<p>But the point of this is to NOT copy the same client key to multiple clients. Think about it. By copying the key around to multiple clients, this means that the key is on every server you ever access from those clients, even if some of the other clients cannot access that server directly. Thus, if a client is compromised, and the key is stolen, it&#8217;s difficult to know which client was compromised, and all servers that have that key in their authorized_keys file, are subject to compromise. If you have a different key for each client, then those keys are only on the servers that the client has direct access to, and should a client become compromised, you know which servers to saefguard, and damage is minimal.</p>
<p><strong>4. Limit the number of clients you SSH from.</strong><br />
If an attacker can compromise your client, then they can get access to your SSH keys, as they are stored on the filesystem. Further, they may be able to install a keylogger to log passwords and passphrases, including those for your key. Once this information is gained, then all the accounts on the servers the key is installed on are now compromised as well. By limiting the number of clients you SSH from, you minimize the exposure of SSH servers to the attacker.</p>
<p><strong>5. Don&#8217;t &#8220;chain&#8221; or &#8220;loop&#8221; logins, but do &#8220;star&#8221;.</strong></p>
<p><img alt="" src="http://lackof.org/taggart/hacking/ssh/ssh.png" title="SSH Scenarios" class="alignnone" width="961" height="262" /></p>
<p>The point relates to the one above it, namely limiting the number of hosts you SSH FROM. There are a few scenarios on how you can create SSH sessions:</p>
<ul>
<li>Chain: As a client, you make a connection with an SSH server. Then, from that server, you make another connection to a different SSH server. Once, twice, three times or more, you&#8217;ve created a chain of connections from the client to the final host.</li>
<li>Loop: As a client, you make a connection with an SSH server. Then, from that server, you make a connection back to the client you started from, thus creating a loop with your connections.</li>
<li>Star: As a client, one connection is made to an SSH server. If another connection is needed to a different SSH server, this is made from the client. For each connection, the original client makes it.</li>
</ul>
<p>The reasons why this is a &#8220;best practice&#8221; might not be obvious. Let&#8217;s start first with chaining connections. If one client is compromised in the chain, the other clients in the chain might possibly be compromised using the same method. Thus, all connections in the chain could become compromised. And a loop is nothing more than a specific instance of a chain.</p>
<p>Of course, this isn&#8217;t always possible. Maybe a chain is the only way to get to an SSH server on a private VLAN or behind a DMZ. These connections might be necessary (typically called &#8220;jump hosts&#8221;), but they should be used with caution, and as little as possible. When you are done with your task, rather than idle the SSH connection, terminate it to minimize exposure, should an attack occur.</p>
<p>When using a jump host, install netcat(1) on the jump host and use the ProxyCommand configuration paramater. Something like this would be sufficient:</p>
<pre>Host inaccessiblehost1 inaccessiblehost2
   ProxyCommand ssh accessiblehost nc -q0 %h %p</pre>
<p>With star connections, you minimize the risk of compromise with each of your connections, but security is maximized, even if extra work is required on your end. For example, if you wish to transfer data from one SSH server to another, this may mean bringing the data to the client, then sending it to the destination server.</p>
<pre></pre>
<p><strong>6. Consider disabling the SSH server on the client you are connecting from.</strong><br />
This rule shouldn&#8217;t apply only to the SSH server, but to any daemon you have running on your machine. If you don&#8217;t need a service running, then turn it off. By doing so, you minimize the attack vector and greatly increase your security. OpenBSD prides itself in having only two remote holes in the default install in a heck of a long time, but then it also doesn&#8217;t have any services running on a default install either.</p>
<p>So, for SSH, because you followed rule #5, and you aren&#8217;t doing &#8220;chain&#8221; or &#8220;loop&#8221; connections from your client, then this means that you&#8217;re not connecting to your own machine that you started your initial connection from. I understand that this isn&#8217;t always possible. I have 300+ SSH servers at work, and I can&#8217;t possible turn off the SSH server on a host, just because I&#8217;m connecting from it. But then, do I need an SSH server on my virtual laptop? Not likely, and if there are things I need, I can turn it on, do my work, then turn it off.</p>
<p><strong>7. Don&#8217;t ignore SSH host key warnings.</strong><br />
When you install an SSH server for the first time, it creates a server public and private keypair. This set of keys is what is used for the encryption and decryption between your client and the SSH server. Thus, all traffic that you are sending to that server, is done because you trust that the SSH server key presented to you, is indeed the key of the server itself. So, what happens when you connect a different time, and your client warns you that the public SSH server key has changed? Should you trust the connection?</p>
<p>Depends. Usually, it&#8217;s due to the fact that you either reinstalled the SSH server or reinstalled the operating system. In this case, you can move forward, so long as you know that the key presented is the new key from the server. However, someone could setup a proxy SSH server, for the intent of gaining system passwords. Your client will warn you the key is different, and you should pay attention to the warning.</p>
<p>So, in your SSH client config, you generally should not set the following:</p>
<pre>Host *
    StrictHostKeyChecking no</pre>
<p>Default is &#8220;yes&#8221;, and it should stay yes in your config. OpenSSH is verbose enough for your benefit. Try to take advantage of it, rather than silence it, or ignore it. After all, it&#8217;s your data.</p>
<p><strong>8. Be wary of using X11 forwarding.</strong><br />
While taking advantage of the ability to run remote X applications locally on your client is nice, it has some very grave drawbacks. For example, it&#8217;s common for people to launch a remote browser, such as Firefox. What isn&#8217;t realized, is that you&#8217;re providing usernames and passwords through the browser, which could be caught on the remote machine from which the app is running (taking advantage of X events, for example).</p>
<p>There is a time and a place for X11 forwarding, and I have benefited by it, but generally, it&#8217;s not needed. Set the following in your SSH client config, and only enable it when needed:</p>
<pre>Host *
    ForwardX11 no</pre>
<p><strong>9. Don&#8217;t use agent forwarding.</strong><br />
As with X11 forwarding, you are giving ultimate trust to the remote host when forwarding your local agent. If that connection makes a connection to an account with superuser privileges, then a user on the remote SSH server could hijack your agent by connecting to the socket the SSH server creates.</p>
<p>Also, on the client initiating the connection, the superuser must be trusted, which isn&#8217;t always the case. The local superuser can access the agent socket on the client, and attack. Thus, it&#8217;s generally not a good idea to enable agent forwarding. Thus, as it is by default, the following should be sent in your client SSH config:</p>
<pre>Host *
    ForwardAgent no</pre>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2011/07/22/openssh-best-practice/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Poll: Have You Ever Used A Floppy Disk?</title>
		<link>http://pthree.org/2011/05/15/poll-have-you-ever-used-a-floppy-disk/</link>
		<comments>http://pthree.org/2011/05/15/poll-have-you-ever-used-a-floppy-disk/#comments</comments>
		<pubDate>Mon, 16 May 2011 00:39:36 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=1899</guid>
		<description><![CDATA[This post is a quickie to see what the current generation is like these days. I&#8217;m an old fart (not as old as many reading this post), but I remember when 5 1/4&#8243; floppy drives were &#8220;standard&#8221;, and 3 1/2&#8243; were the new fad. Then came Iomega Jazz drives, and the like. CDRW hit the [...]]]></description>
			<content:encoded><![CDATA[<p>This post is a quickie to see what the current generation is like these days. I&#8217;m an old fart (not as old as many reading this post), but I remember when 5 1/4&#8243; floppy drives were &#8220;standard&#8221;, and 3 1/2&#8243; were the new fad. Then came Iomega Jazz drives, and the like. CDRW hit the scene, never really went far, then USB storage was here, and here to stay.</p>
<p>At any event, in graphical user interfaces, you&#8217;ll see floppy disks that represent saving a file to disk. It&#8217;s very, very common, yet <a href="http://i.imgur.com/vBIC1.png">I doubt many of the younger generation has ever used one</a>. So, how are they supposed to know what it does?</p>
<p>So, here&#8217;s a poll for you to take. You&#8217;ll need to take the poll at my site, as it uses Ajax calls to the page, which means it won&#8217;t work in your RSS reader, or on any other site. I&#8217;m just curious to see what falls out.</p>
<div>
	<div class='democracy'>
		<strong class="poll-question">Have you ever used a floppy disk?</strong>
		<div class='dem-results'>
		<form action='http://pthree.org/wp-content/plugins/democracy/democracy.php' onsubmit='return dem_Vote(this)'>
		<ul>
			<li>
					<input type='radio' id='dem-choice-38' value='38' name='dem_poll_7' />
					<label for='dem-choice-38'>Yes, and I STILL use them!</label>
			</li>
			<li>
					<input type='radio' id='dem-choice-39' value='39' name='dem_poll_7' />
					<label for='dem-choice-39'>Yes, but not anymore.</label>
			</li>
			<li>
					<input type='radio' id='dem-choice-40' value='40' name='dem_poll_7' />
					<label for='dem-choice-40'>No, but I've physically seen one.</label>
			</li>
			<li>
					<input type='radio' id='dem-choice-41' value='41' name='dem_poll_7' />
					<label for='dem-choice-41'>What's a floppy disk?</label>
			</li>
		</ul>
			<input type='hidden' name='dem_poll_id' value='7' />
			<input type='hidden' name='dem_action' value='vote' />
			<input type='submit' class='dem-vote-button' value='Vote' />
			<a href='/category/linux/feed/?dem_action=view&amp;dem_poll_id=7' onclick='return dem_getVotes("http://pthree.org/wp-content/plugins/democracy/democracy.php?dem_action=view&amp;dem_poll_id=7", this)' rel='nofollow' class='dem-vote-link'>View Results</a>
		</form>
		</div>
	</div></div>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2011/05/15/poll-have-you-ever-used-a-floppy-disk/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Why Unix Is Superior</title>
		<link>http://pthree.org/2011/03/27/why-unix-is-superior/</link>
		<comments>http://pthree.org/2011/03/27/why-unix-is-superior/#comments</comments>
		<pubDate>Mon, 28 Mar 2011 04:34:20 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Debian]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=1834</guid>
		<description><![CDATA[Quick post, outlining what I think makes the Unix family of operating systems superior, including &#8220;unix-like&#8221; operating systems such as GNU/Linux, BSD, and others. Of course, the list isn&#8217;t exhaustive- it&#8217;s just something I threw together in 10 minutes. The motivation of the post was a discussion in ##unix on Freenode. The command line interface. [...]]]></description>
			<content:encoded><![CDATA[<p>Quick post, outlining what I think makes the Unix family of operating systems superior, including &#8220;unix-like&#8221; operating systems such as GNU/Linux, BSD, and others. Of course, the list isn&#8217;t exhaustive- it&#8217;s just something I threw together in 10 minutes. The motivation of the post was a discussion in 	<a href="irc://irc.freenode.net/##unix">##unix on Freenode</a>.</p>
<ol>
<li>The command line interface.</li>
<li>Various shells, including their script syntax.</li>
<li>Builtin programming language support for many languages.</li>
<li>Common Unix utilities, such as grep, rsync, ssh, lsof, and others.</li>
<li>All the supported filesystems (ZFS, Ext4, Reiser, UFS, etc.).</li>
<li>Overall rock-solid stability and reliability.</li>
<li>Lack of viruses, trojans, and other malware.</li>
<li>Tremendous networking capabilities (PPoE, TCP/IP, etc.).</li>
<li>Bulletproof firewall software.</li>
<li>Overall builtin security in general (MACs, PAM, etc.).</li>
<li>Quality user/group management.</li>
<li>System resource usage.</li>
<li>Both vertical and horizontal scaling.</li>
<li>Portability.</li>
<li>Plain text configuration files.</li>
<li>Open source kernel and user-space software.</li>
<li>Based on standards (POSIX, FHS, LSB, etc.).</li>
<li>Vast selection of software choices (various text editors, MUAs, etc.)</li>
<li>Simplicity in software design- do one thing, and do it well.</li>
<li>Mind-blowing hardware support.</li>
<li>Support for hundreds of languages and locales out of the box.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2011/03/27/why-unix-is-superior/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Various Ways To Shred A Drive</title>
		<link>http://pthree.org/2011/03/09/various-ways-to-shred-a-drive/</link>
		<comments>http://pthree.org/2011/03/09/various-ways-to-shred-a-drive/#comments</comments>
		<pubDate>Thu, 10 Mar 2011 05:00:21 +0000</pubDate>
		<dc:creator>Aaron Toponce</dc:creator>
				<category><![CDATA[Debian]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://pthree.org/?p=1793</guid>
		<description><![CDATA[I&#8217;ve been tasked at work with shredding drives. Not physically, mind you, but digitally. Usually, I grab a copy of the latest version of Knoppix, boot up, pull up a terminal, and grab GNU Shred. Something like: shred -n 3 -v /dev/sda It works well enough. However, it doesn&#8217;t display a real useful progress meter, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been tasked at work with shredding drives. Not physically, mind you, but digitally. Usually, I grab a copy of the latest version of Knoppix, boot up, pull up a terminal, and grab GNU Shred. Something like:</p>
<pre>shred -n 3 -v /dev/sda</pre>
<p>It works well enough. However, it doesn&#8217;t display a real useful progress meter, other than how far it&#8217;s done in the wipe, thus leaving it up to you to figure out the speed, while filling up your back scroll in the process. There must be a better way.</p>
<p>I used to &#8220;<a href="http://pthree.org/2008/08/17/digital-graffiti/">leave my mark</a>&#8221; (much like a dog marks a fire hydrant), however, this is quite slow. There are other methods, such as using /dev/urandom, but the entropy from urandom relies on SHA1. While fast, it&#8217;s not the speed demon that is AES or other algorithms. There&#8217;s /dev/zero, but how do I get random bits from zeros? And more importantly, does it push the drive to it&#8217;s bandwidth threshold? Of course, I&#8217;ve heard about DBAN, but I&#8217;ve had issues with it booting on certain hardware. Lastly, I would like to have a good progress meter as the data goes down on the drive.</p>
<p>Here&#8217;s a solution that a friend of mine in an IRC channel suggested:</p>
<pre>openssl enc -aes128 -k "foo" &lt; /dev/zero | pv -trb &gt; /dev/sda</pre>
<p>The great thing with this command is two fold:</p>
<ol>
<li>It&#8217;s fast. It pushes the drive to as fast as it can write data.</li>
<li>It provides a convenient progress meter with &#8220;pv&#8221;</li>
</ol>
<p>Again, I&#8217;m shredding drives with pseudorandom data. I&#8217;m not too concerned about the security of the bits going down on the platter. Per corporate regulation, I need to do 3 passes, and I&#8217;m confident that the bits coming out of the pipe from OpenSSL using AES-128 will be sufficient. So, for doing 3 passes, I can script it easily enough:</p>
<pre>for I in 1 2 3; do
    openssl enc -aes128 -k "$I" &lt; /dev/zero | pv -trb &gt; /dev/sda
done</pre>
<p>That works. 1 drive down, 24 to go&#8230;</p>
<p>If you have various ways you shred your drive, let me know, and I&#8217;ll post it below.</p>
]]></content:encoded>
			<wfw:commentRss>http://pthree.org/2011/03/09/various-ways-to-shred-a-drive/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>

