<?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>BASH Cures Cancer &#187; Shell</title>
	<atom:link href="http://bashcurescancer.com/category/shell/feed" rel="self" type="application/rss+xml" />
	<link>http://bashcurescancer.com</link>
	<description>Learn the UNIX/Linux command line</description>
	<lastBuildDate>Sat, 31 Jul 2010 17:30:08 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>UNIX Text Processing</title>
		<link>http://bashcurescancer.com/unix-text-processing.html</link>
		<comments>http://bashcurescancer.com/unix-text-processing.html#comments</comments>
		<pubDate>Sat, 31 Jul 2010 17:30:08 +0000</pubDate>
		<dc:creator>Brock Noland</dc:creator>
				<category><![CDATA[Shell]]></category>

		<guid isPermaLink="false">http://bashcurescancer.com/?p=184</guid>
		<description><![CDATA[I am at the library in Minneapolis and I just ran across UNIX Text Processing which you can buy for less than a single USD.  Buy that book and my work here is done.
]]></description>
			<content:encoded><![CDATA[<p>I am at the library in Minneapolis and I just ran across <a href="http://www.amazon.com/Unix-Text-Processing-Dale-Dougherty/dp/0810462915">UNIX Text Processing</a> which you can buy for less than a single USD.  Buy that book and my work here is done.</p>
]]></content:encoded>
			<wfw:commentRss>http://bashcurescancer.com/unix-text-processing.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Shelling scripting is a necessary skill</title>
		<link>http://bashcurescancer.com/shelling-scripting-is-a-necessary-skill.html</link>
		<comments>http://bashcurescancer.com/shelling-scripting-is-a-necessary-skill.html#comments</comments>
		<pubDate>Tue, 23 Mar 2010 21:22:19 +0000</pubDate>
		<dc:creator>Brock Noland</dc:creator>
				<category><![CDATA[Shell]]></category>

		<guid isPermaLink="false">http://bashcurescancer.com/?p=180</guid>
		<description><![CDATA[Yesterday a 20 line shell script caught a race condition in one of software I work on. Our best engineers looked at the problem, a vendor case was filed, and there was thoughts of automatically restarted the application to fix the issue at hand.
In the end, a 20 line shell script to strace for file [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday a 20 line shell script caught a race condition in one of software I work on. Our best engineers looked at the problem, a vendor case was filed, and there was thoughts of automatically restarted the application to fix the issue at hand.</p>
<p>In the end, a 20 line shell script to strace for file operations continuously provided the needed visibility into the issue at hand.</p>
<p>Update: The shell script.</p>
<p>The shell script itself, though trivial, is owned by the company I work for, but the basic concept was as follows:</p>
<p>#!/bin/bash</p>
<p># loop forever<br />
while sleep 60<br />
do<br />
     pid=$(ps -ef | grep application | egrep -v grep | awk &#8216;{print $2}&#8217;)<br />
     if [[ -n $pid ]]<br />
     then<br />
           outfile=strace-application-$(date +%Y%M%d-%H:%M:%S).out.gz<br />
           strace -tt -f -e trace=file -p $pid 2>&#038;1 | gzip -c > $outfile<br />
     fi<br />
done</p>
]]></content:encoded>
			<wfw:commentRss>http://bashcurescancer.com/shelling-scripting-is-a-necessary-skill.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Splitting Strings Natively with the Shell: Native vs Native</title>
		<link>http://bashcurescancer.com/splitting-strings-natively-with-the-shell-native-vs-native.html</link>
		<comments>http://bashcurescancer.com/splitting-strings-natively-with-the-shell-native-vs-native.html#comments</comments>
		<pubDate>Thu, 10 Dec 2009 04:57:30 +0000</pubDate>
		<dc:creator>Brock Noland</dc:creator>
				<category><![CDATA[Shell]]></category>

		<guid isPermaLink="false">http://bashcurescancer.com/?p=173</guid>
		<description><![CDATA[Splitting Strings Natively with the Shell: Native vs Native
In my previous post on why to split strings with bash itself, I used set to split the string.
This was much faster than using a sub-shell and awk or cut.  However, we can do better!  The read command accepts a list of variables to split [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://bashcurescancer.com/splitting-strings-natively-with-the-shell-native-vs-native.html">Splitting Strings Natively with the Shell: Native vs Native</a></p>
<p>In my previous post on <a href="http://bashcurescancer.com/splitting-strings-natively-with-the-shell-why.html">why to split strings with bash</a> itself, I used set to split the string.</p>
<p>This was much faster than using a sub-shell and awk or cut.  However, we can do better!  The read command accepts a list of variables to split the input.  Combined with setting a per command variable, we can write an even more elegant solution.</p>
<p>The magic is here:</p>
<pre>
while IFS=: read username x uid gid gecos home shell
</pre>
<p>We set IFS=: only for the execution of read, so there is no need to reset it once done splitting the string.  Second we read each field (separated by : via IFS) into a variable directly.</p>
<p>Below is the script we will use to compare the two methods.  You will notice I had to up the iterations to 100 in order to see a difference in execution speed:</p>
<pre>
[root@sandbox ~]# cat ifs-test2.sh
#!/bin/bash
split_words_native() {
    # execute 100 times
    for i in {0..100}
    do
        while read line
        do
            oldIFS=$IFS
            IFS=:
            set -- $line
            IFS=$oldIFS
            # at this point $1 is the username, $3
            # is the uid, and $7 is the shell
            if [[ $3 -gt 10 ]] &#038;&#038; [[ '/sbin/nologin' == "$7" ]]
            then
                echo $1
            fi
        done < /etc/passwd
    done
}

split_words_native_read() {
    # execute 100 times
    for i in {0..100}
    do
        while IFS=: read username x uid gid gecos home shell
        do
            if [[ $uid -gt 10 ]] &#038;&#038; [[ '/sbin/nologin' == "$shell" ]]
            then
                echo $username
            fi
        done < /etc/passwd
done
}
echo "---Native---"
time split_words_native >/dev/null
echo -e "\n---Read---"
time split_words_native_read >/dev/null
</pre>
<p>Using read is more elegant and a little faster:</p>
<pre>
[root@sandbox ~]# ./ifs-test2.sh
---Native---

real    0m0.179s
user    0m0.168s
sys     0m0.010s

---Read---

real    0m0.147s
user    0m0.135s
sys     0m0.012s
</pre>
]]></content:encoded>
			<wfw:commentRss>http://bashcurescancer.com/splitting-strings-natively-with-the-shell-native-vs-native.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Splitting Strings Natively with the Shell: Why</title>
		<link>http://bashcurescancer.com/splitting-strings-natively-with-the-shell-why.html</link>
		<comments>http://bashcurescancer.com/splitting-strings-natively-with-the-shell-why.html#comments</comments>
		<pubDate>Wed, 09 Dec 2009 23:18:39 +0000</pubDate>
		<dc:creator>Brock Noland</dc:creator>
				<category><![CDATA[Shell]]></category>

		<guid isPermaLink="false">http://bashcurescancer.com/?p=167</guid>
		<description><![CDATA[Today I want to discuss splitting strings into tokens or &#8220;words&#8221;.  I previously discussed how to do this with the IFS variable and promised a more in depth discussion.  Today, I will make the case on WHY to use IFS to split strings as opposed to using a subshell combined with awk or [...]]]></description>
			<content:encoded><![CDATA[<p>Today I want to discuss splitting strings into tokens or &#8220;words&#8221;.  I previously discussed how to do this with the <a href="http://bashcurescancer.com/reading-a-file-line-by-line.html">IFS variable</a> and promised a more in depth discussion.  Today, I will make the case on WHY to use IFS to split strings as opposed to using a subshell combined with awk or cut.</p>
<p>I wrote this script which reads the /etc/password file line-by-line and prints the username of any user which has a UID greater than 10 and has the shell of /sbin/nologin.  Each test function performs this task 10 times to increase the length of the test:</p>
<pre>
[root@sandbox ~]# cat ifs-test.sh
#!/bin/bash
split_words_cut() {
       # execute 10 times
        for i in {0..9}
        do
                while read line
                do
                        # get uid
                        id=$(echo $line | cut -d: -f3)
                        if [[ $id -gt 10 ]]
                        then
                                # get shell
                                shell=$(echo $line | echo $line | cut -d: -f7)
                                if [[ '/sbin/nologin' == "$shell" ]]
                                then
                                        # print username
                                        echo $line | cut -d: -f1
                                fi
                        fi
                done < /etc/passwd
        done
}

split_words_awk() {
        # execute 10 times
        for i in {0..9}
        do
                while read line
                do
                        # get uid
                        id=$(echo $line | awk -F: '{print $3}')
                        if [[ $id -gt 10 ]]
                        then
                                # get shell
                                shell=$(echo $line | awk -F: '{print $NF}')
                                if [[ '/sbin/nologin' == "$shell" ]]
                                then
                                        # print username
                                        echo $line | awk -F: '{print $1}'
                                fi
                        fi
                done < /etc/passwd
        done
}
split_words_native() {
        # execute 10 times
        for i in {0..9}
        do
                while read line
                do
                        oldIFS=$IFS
                        IFS=:
                        set -- $line
                        IFS=$oldIFS
                        # at this point $1 is the username, $3
                        # is the uid, and $7 is the shell
                        if [[ $3 -gt 10 ]] &#038;&#038; [[ '/sbin/nologin' == "$7" ]]
                        then
                              echo $1
                        fi
                done < /etc/passwd
        done
}
echo -e "---Cut---"
time split_words_cut >/dev/null
echo -e "\n---Awk---"
time split_words_awk >/dev/null
echo -e "\n---Native---"
time split_words_native >/dev/null
</pre>
<p>As you can see, using the shell itself is about two orders of magnitude faster than using the subshell awk/cut method:</p>
<pre>
[root@sandbox ~]# ./ifs-test.sh
---Cut---

real    0m1.184s
user    0m0.118s
sys     0m0.676s

---Awk---

real    0m1.279s
user    0m0.151s
sys     0m0.750s

---Native---

real    0m0.018s
user    0m0.014s
sys     0m0.003s
</pre>
<p>This is why you should using IFS when splitting strings&#8230;.</p>
]]></content:encoded>
			<wfw:commentRss>http://bashcurescancer.com/splitting-strings-natively-with-the-shell-why.html/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Reading a file, line by line</title>
		<link>http://bashcurescancer.com/reading-a-file-line-by-line.html</link>
		<comments>http://bashcurescancer.com/reading-a-file-line-by-line.html#comments</comments>
		<pubDate>Tue, 24 Nov 2009 23:15:09 +0000</pubDate>
		<dc:creator>Brock Noland</dc:creator>
				<category><![CDATA[Shell]]></category>

		<guid isPermaLink="false">http://bashcurescancer.com/?p=155</guid>
		<description><![CDATA[nixcraft has a link on how to read a file line by line.  The method is a great way to read a file, but there some trouble spots I thought I would point out.
In the script, the special variable IFS is set:

# set the Internal Field Separator to a pipe symbol
IFS='&#124;'

The tells the read [...]]]></description>
			<content:encoded><![CDATA[<p>nixcraft has a <a href="http://www.cyberciti.biz/faq/ksh-read-file/">link</a> on how to read a file line by line.  The method is a great way to read a file, but there some trouble spots I thought I would point out.</p>
<p>In the script, the special variable IFS is set:</p>
<pre>
# set the Internal Field Separator to a pipe symbol
IFS='|'
</pre>
<p>The tells the read command to split &#8220;cyberciti.biz|74.86.48.99&#8243; into &#8220;cyberciti.biz&#8221; and &#8220;74.86.48.99&#8243; and thus fill both the domain and ip variables here:</p>
<pre>while read domain ip</pre>
<p>Using BASH to split strings is much faster than doing something line this:</p>
<pre>
while read line
do
   domain=$(echo $line | awk -F'|' '{print $1}'
   ip=$(echo $line | awk -F'|' '{print $2}'
</pre>
<p>As new script writers typically do.  However, setting IFS and forgetting to reset the special variable can cause some odd problems in longer scripts.  For example, lets say you needed to read a second file, later on in the script.  This one delimited by spaces.  For simplicity, I will take the same file and just replace the pipe characters with spaces.</p>
<p><strong>/tmp/domains-using-space.txt</strong></p>
<pre>
root@b92 [~]# cat /tmp/domains-using-space.txt
cyberciti.biz 74.86.48.99
nixcraft.com 75.126.168.152
theos.in 75.126.168.153
cricketnow.in 75.126.168.154
vivekgite.com 75.126.168.155
</pre>
<p>Now, here is my new script:</p>
<pre>
#!/bin/ksh
# set the Internal Field Separator to a pipe symbol
IFS='|'

# file name
file=/tmp/domains.txt

# use while loop to read domain and ip
while read domain ip
do
    print "$domain has address $ip"
done <"$file"

echo ------------------------
file=/tmp/domains-using-space.txt

# use while loop to read domain and ip
while read domain ip
do
    print "$domain has address $ip"
done <"$file"
</pre>
<p>As you can see, the output is incorrect:</p>
<pre>root@b92 [~]# ./test.sh
cyberciti.biz has address 74.86.48.99
nixcraft.com has address 75.126.168.152
theos.in has address 75.126.168.153
cricketnow.in has address 75.126.168.154
vivekgite.com has address 75.126.168.155
------------------------
cyberciti.biz 74.86.48.99 has address
nixcraft.com 75.126.168.152 has address
theos.in 75.126.168.153 has address
cricketnow.in 75.126.168.154 has address
vivekgite.com 75.126.168.155 has address
</pre>
<p>By saving and resetting the special variable IFS, we can eliminate this problem:</p>
<pre>#!/bin/ksh
# file name
file=/tmp/domains.txt

# set the Internal Field Separator to a pipe symbol
oldIFS="$IFS"
IFS='|'

# use while loop to read domain and ip
while read domain ip
do
    print "$domain has address $ip"
done <"$file"
IFS="$oldIFS"

echo ------------------------
file=/tmp/domains-using-space.txt

# use while loop to read domain and ip
while read domain ip
do
    print "$domain has address $ip"
done <"$file"
</pre>
<p>The output from the new script, which saves and resets IFS:</p>
<pre>
cyberciti.biz has address 74.86.48.99
nixcraft.com has address 75.126.168.152
theos.in has address 75.126.168.153
cricketnow.in has address 75.126.168.154
vivekgite.com has address 75.126.168.155
------------------------
cyberciti.biz has address 74.86.48.99
nixcraft.com has address 75.126.168.152
theos.in has address 75.126.168.153
cricketnow.in has address 75.126.168.154
vivekgite.com has address 75.126.168.155
</pre>
<p>In short, IFS is a great way to split strings.  My next article will be a more in depth discussion of this topic.  In the mean time, one item to remember when using IFS, is to always save and reset this variable.</p>
]]></content:encoded>
			<wfw:commentRss>http://bashcurescancer.com/reading-a-file-line-by-line.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>The best in command line xml: XMLStarlet</title>
		<link>http://bashcurescancer.com/the-best-in-command-line-xml-xmlstarlet.html</link>
		<comments>http://bashcurescancer.com/the-best-in-command-line-xml-xmlstarlet.html#comments</comments>
		<pubDate>Tue, 24 Jun 2008 04:32:48 +0000</pubDate>
		<dc:creator>Brock Noland</dc:creator>
				<category><![CDATA[Links]]></category>
		<category><![CDATA[Shell]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://bashcurescancer.com/?p=151</guid>
		<description><![CDATA[Quite some time ago I wrote about using xsltproc to process xml on the command line. Thank fully someone pointed out XMLStarlet.  I now use XMLStarlet almost every day.  I work with a variety of REST based API&#8217;s gather information. XMLStartlet along with a simple for loop or xargs gives you an exceedingly powerful set [...]]]></description>
			<content:encoded><![CDATA[<p>Quite some time ago I wrote about using xsltproc to process xml on the command line. Thank fully someone pointed out <a href="http://xmlstar.sourceforge.net/">XMLStarlet</a>.  I now use XMLStarlet almost every day.  I work with a variety of REST based API&#8217;s gather information. XMLStartlet along with a simple for loop or xargs gives you an exceedingly powerful set of tools.</p>
<p>Here is a quick introduction into the power of XMLStarlet. This is just a teaser as I cannot share the data I work with. However, you should be able to see the power of this tool.</p>
<p>All the links from my RSS feed:</p>
<pre>$ curl -s 'http://bashcurescancer.com/rss/' | xml sel -t -m '//link' -v '.' -n

http://bashcurescancer.com</pre>
<pre>http://bashcurescancer.com/processing-xml-on-the-command-line.html

http://bashcurescancer.com/do-not-close-stderr.html</pre>
<pre>http://bashcurescancer.com/prepend-to-a-file-with-sponge-from-moreutils.html</pre>
<pre>http://bashcurescancer.com/bug-in-curl-is-fixed.html</pre>
<pre>http://bashcurescancer.com/using-kill-to-see-if-a-process-is-alive.html</pre>
<pre>http://bashcurescancer.com/performance-testing-with-curl.html</pre>
<pre>http://bashcurescancer.com/new-command-prepend.html</pre>
<pre>http://bashcurescancer.com/shell-function-which-webserver-does-that-site-run.html</pre>
<pre>http://bashcurescancer.com/exposing-command-line-programs-as-web-services.html

http://bashcurescancer.com/wrapping-dynamic-languages-in-shell-without-an-extra-script.html</pre>
<p>Or how about &#8220;Title: link&#8221;</p>
<pre>$ curl -s 'http://bashcurescancer.com/rss/' | xml sel -t -m '//item' -v 'title' -o ': ' -v 'link' -n</pre>
<pre>Processing XML on the Command Line: http://bashcurescancer.com/processing-xml-on-the-command-line.html</pre>
<pre>Do not close stderr: http://bashcurescancer.com/do-not-close-stderr.html</pre>
<pre>prepend to a file with sponge from moreutils: http://bashcurescancer.com/prepend-to-a-file-with-sponge-from-moreutils.html</pre>
<pre>Bug in Curl is fixed: http://bashcurescancer.com/bug-in-curl-is-fixed.html</pre>
<pre>using kill to see if a process is alive: http://bashcurescancer.com/using-kill-to-see-if-a-process-is-alive.html</pre>
<pre>Performance testing - with curl: http://bashcurescancer.com/performance-testing-with-curl.html</pre>
<pre>New command: prepend: http://bashcurescancer.com/new-command-prepend.html</pre>
<pre>Shell Function - Which Webserver Does That Site Run?: http://bashcurescancer.com/shell-function-which-webserver-does-that-site-run.html</pre>
<pre>Exposing command line programs as web services: http://bashcurescancer.com/exposing-command-line-programs-as-web-services.html</pre>
<pre>Wrapping dynamic languages in shell without an extra script: http://bashcurescancer.com/wrapping-dynamic-languages-in-shell-without-an-extra-script.html</pre>
<p>You may need to do some reading on xpaths and xsl stylesheets to use the full power of the tool.</p>
]]></content:encoded>
			<wfw:commentRss>http://bashcurescancer.com/the-best-in-command-line-xml-xmlstarlet.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Do not close stderr</title>
		<link>http://bashcurescancer.com/do-not-close-stderr.html</link>
		<comments>http://bashcurescancer.com/do-not-close-stderr.html#comments</comments>
		<pubDate>Wed, 23 Apr 2008 04:25:26 +0000</pubDate>
		<dc:creator>Brock Noland</dc:creator>
				<category><![CDATA[Shell]]></category>
		<category><![CDATA[examples]]></category>
		<category><![CDATA[good practices]]></category>
		<category><![CDATA[stderr]]></category>
		<category><![CDATA[thanks]]></category>
		<category><![CDATA[things not todo]]></category>

		<guid isPermaLink="false">http://bashcurescancer.com/?p=148</guid>
		<description><![CDATA[A few years ago, I wrote a post commenting on how ugly this was:
$ someprog 2&#62;/dev/null
I was nearly imploring the reader to close stderr:
$ someprog 2&#62;&#38;-
Some very knowledgeable anonymous commenter explained why that was a bad idea. At the time, I didn&#8217;t understand exactly what they were saying. As such, I deleted the post. Yesterday, [...]]]></description>
			<content:encoded><![CDATA[<p>A few years ago, I wrote a post commenting on how ugly this was:</p>
<pre>$ someprog 2&gt;/dev/null</pre>
<p>I was nearly imploring the reader to close stderr:</p>
<pre>$ someprog 2&gt;&amp;-</pre>
<p>Some very knowledgeable anonymous commenter explained why that was a bad idea. At the time, I didn&#8217;t understand exactly what they were saying. As such, I deleted the post. Yesterday, for no particular reason, the implications of closing stderr popped into my head. In the shower no less.</p>
<p>I wrote a simple little C program named <a href="http://bashcurescancer.com/media/misc/do-not-close-stderr.c">do-not-close-stderr.c</a>. It takes two parameters, a string you want written to a file and the file you want said string written to. After opening the file, it prints &#8220;some kind of warning message&#8221; to stderr. Here we are:</p>
<pre>$ gcc -Wall do-not-close-stderr.c -o do-not-close-stderr
$ ./do-not-close-stderr "Brock was here." output
Some kind of warning message.
$ cat output
Brock was here.</pre>
<p>Now lets close standard error when executing:</p>
<pre>$ ./do-not-close-stderr "Brock was here." output 2&gt;&amp;-
$ cat output
Some kind of warning message.
Brock was here.</pre>
<p>Thanks to whoever that commenter was.</p>
]]></content:encoded>
			<wfw:commentRss>http://bashcurescancer.com/do-not-close-stderr.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>prepend to a file with sponge from moreutils</title>
		<link>http://bashcurescancer.com/prepend-to-a-file-with-sponge-from-moreutils.html</link>
		<comments>http://bashcurescancer.com/prepend-to-a-file-with-sponge-from-moreutils.html#comments</comments>
		<pubDate>Thu, 17 Apr 2008 19:37:37 +0000</pubDate>
		<dc:creator>Brock Noland</dc:creator>
				<category><![CDATA[Contributions]]></category>
		<category><![CDATA[Shell]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[moreutils]]></category>
		<category><![CDATA[patches]]></category>
		<category><![CDATA[prepend]]></category>

		<guid isPermaLink="false">http://bashcurescancer.com/?p=147</guid>
		<description><![CDATA[A few weeks I wrote about a tool, which helps you easily prepend to a file. I submitted prepend to moreutils and Joey was kind enough to point out this could be done with `sponge&#8217;.  sponge reads standard input and when done, writes it to a file:
Probably the most general purpose tool in moreutils so [...]]]></description>
			<content:encoded><![CDATA[<p>A few weeks I wrote about a tool, which helps you <a href="http://bashcurescancer.com/new-command-prepend.html">easily prepend to a file</a>. I submitted prepend to <a href="http://kitenet.net/~joey/code/moreutils/">moreutils</a> and Joey was kind enough to point out this could be done with `sponge&#8217;.  sponge reads standard input and when done, writes it to a file:</p>
<blockquote><p>Probably the most general purpose tool in <a href="http://kitenet.net/~joey/code/moreutils/">moreutils </a>so far is <code>sponge</code>(1), which lets you do things like this:</p>
<p><code>% sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd</code></p></blockquote>
<p>Two days ago Joey released version 0.29 of <a href="http://kitenet.net/~joey/code/moreutils/">moreutils </a>including a patch by yours truly (with much help from Joey).</p>
<blockquote><p>sponge: Handle large data sizes by using a temp file rather than by  consuming arbitrary amounts of memory. Patch by Brock Noland. <a href="http://kitenet.net/~joey/code/moreutils/news/version_0.29/">version 0.29 changelog</a></p></blockquote>
<p>Also, on a non-command line note, I found a video on Joey&#8217;s site which I thought was pretty cool, <a href="http://kitenet.net/~joey/learnstofly/">Joey Learns to Fly</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://bashcurescancer.com/prepend-to-a-file-with-sponge-from-moreutils.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>using kill to see if a process is alive</title>
		<link>http://bashcurescancer.com/using-kill-to-see-if-a-process-is-alive.html</link>
		<comments>http://bashcurescancer.com/using-kill-to-see-if-a-process-is-alive.html#comments</comments>
		<pubDate>Thu, 10 Apr 2008 04:43:55 +0000</pubDate>
		<dc:creator>Brock Noland</dc:creator>
				<category><![CDATA[Brock's Tools]]></category>
		<category><![CDATA[Good Practice]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Shell]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[kill]]></category>
		<category><![CDATA[process]]></category>
		<category><![CDATA[ps]]></category>
		<category><![CDATA[ps -ef]]></category>
		<category><![CDATA[ps faux]]></category>
		<category><![CDATA[ps grep]]></category>

		<guid isPermaLink="false">http://bashcurescancer.com/?p=141</guid>
		<description><![CDATA[I am making some changes to the moreutils sponge command.  Sponge provides a method of prepending which is less specialized than my prepend util. However, it has trouble with large amounts of input.
Regardless, while testing my changes, I want to watch it operate. Normally, you would just do so from a second terminal. That [...]]]></description>
			<content:encoded><![CDATA[<p>I am making some changes to the <a href="http://kitenet.net/~joey/code/moreutils/">moreutils</a> sponge command.  Sponge provides a method of prepending which is less specialized than my <a href="http://bashcurescancer.com/new-command-prepend.html">prepend</a> util. However, it has trouble with large amounts of input.</p>
<p>Regardless, while testing my changes, I want to watch it operate. Normally, you would just do so from a second terminal. That is a pain. kill -0 can be very useful for this. After backgrounding the command, I assign the pid (via the variable $!) to $pid using eval. eval is needed to stop BASH from expanding $! until after the background operation.</p>
<p>After that, I enter a while loop on kill -0 $pid, which will not kill $pid, but will return successfully until $pid has died:</p>
<pre># cat large-file-GB | ./sponge large-file-GB-copy &amp; eval 'pid=$!'; while kill -0 $pid; do sleep 10; ls -lh large-file* /tmp/sponge.*; echo;done
[1] 7937
-rw-r--r-- 1 root root 977M 2008-04-09 16:18 large-file-GB
-rw------- 1 root root 128M 2008-04-09 17:23 /tmp/sponge.JMsBWG

-rw-r--r-- 1 root root 977M 2008-04-09 16:18 large-file-GB
-rw------- 1 root root 384M 2008-04-09 17:23 /tmp/sponge.JMsBWG

-rw-r--r-- 1 root root 977M 2008-04-09 16:18 large-file-GB
-rw------- 1 root root 877M 2008-04-09 17:24 /tmp/sponge.JMsBWG

-rw-r--r-- 1 root root 977M 2008-04-09 16:18 large-file-GB
-rw-r--r-- 1 root root  20M 2008-04-09 17:24 large-file-GB-copy
-rw------- 1 root root 896M 2008-04-09 17:24 /tmp/sponge.JMsBWG

-rw-r--r-- 1 root root 977M 2008-04-09 16:18 large-file-GB
-rw-r--r-- 1 root root 413M 2008-04-09 17:25 large-file-GB-copy
-rw------- 1 root root 896M 2008-04-09 17:24 /tmp/sponge.JMsBWG

-rw-r--r-- 1 root root 977M 2008-04-09 16:18 large-file-GB
-rw-r--r-- 1 root root 836M 2008-04-09 17:25 large-file-GB-copy
-rw------- 1 root root 896M 2008-04-09 17:24 /tmp/sponge.JMsBWG

-rw-r--r-- 1 root root 977M 2008-04-09 16:18 large-file-GB
-rw-r--r-- 1 root root 920M 2008-04-09 17:25 large-file-GB-copy
[1]+  Done                    cat large-file-GB | ./sponge large-file-GB-copy
ls: cannot access /tmp/sponge.*: No such file or directory

-rw-r--r-- 1 root root 977M 2008-04-09 16:18 large-file-GB
-rw-r--r-- 1 root root 977M 2008-04-09 17:25 large-file-GB-copy
-bash: kill: (7937) - No such process
# md5sum large-file-GB*
b5c667a723a10a3485a33263c4c2b978  large-file-GB
b5c667a723a10a3485a33263c4c2b978  large-file-GB-copy</pre>
]]></content:encoded>
			<wfw:commentRss>http://bashcurescancer.com/using-kill-to-see-if-a-process-is-alive.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Performance testing &#8211; with curl</title>
		<link>http://bashcurescancer.com/performance-testing-with-curl.html</link>
		<comments>http://bashcurescancer.com/performance-testing-with-curl.html#comments</comments>
		<pubDate>Tue, 08 Apr 2008 05:21:46 +0000</pubDate>
		<dc:creator>Brock Noland</dc:creator>
				<category><![CDATA[Good Practice]]></category>
		<category><![CDATA[Shell]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[speed]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://bashcurescancer.com/?p=139</guid>
		<description><![CDATA[Often I need or want to do some type of performance testing. Given my ideas on software development, I can usually do this by making simple HTTP requests. I use curl for this. While you may be tempted to do this in a for loop (or worse, actually write something!):
$ time for i in {1..1000}; [...]]]></description>
			<content:encoded><![CDATA[<p>Often I need or want to do some type of performance testing. Given <a href="http://bashcurescancer.com/3-principles-of-web-application-design-for-the-command-line.html">my ideas on software development</a>, I can usually do this by making simple HTTP requests. I use curl for this. While you may be tempted to do this in a for loop (or worse, actually write something!):</p>
<pre>$ time for i in {1..1000}; do curl -s "http://bashcurescancer.com/blank.html";done</pre>
<pre>real    0m23.436s
user    0m6.416s
sys     0m7.351s</pre>
<p>Curl provides the same functionality:</p>
<pre>$ time curl -s "http://bashcurescancer.com/blank.html?[1-1000]"</pre>
<pre>real    0m6.561s
user    0m0.294s
sys     0m0.494s</pre>
<p>Here are the details from the curl manual:</p>
<blockquote><p>The URL syntax is protocol dependent. You’ll find a detailed description in RFC 3986.</p>
<p>You can specify multiple URLs or parts of URLs by writing part sets within braces as in:</p>
<p>http://site.{one,two,three}.com</p>
<p>or you can get sequences of alphanumeric series by using [ ] as in:</p>
<p>ftp://ftp.numericals.com/file[1-100].txt<br />
ftp://ftp.numericals.com/file[001-100].txt    (with leading zeros)<br />
ftp://ftp.letters.com/file[a-z].txt</p>
<p>No nesting of the sequences is supported at the moment, but you can use several ones next to each other:</p>
<p>http://any.org/archive[1996-1999]/vol[1-4]/part{a,b,c}.html</p>
<p>You can specify any amount of URLs on the command line. They will be fetched in a sequential manner in the specified order.</p>
<p>Since curl 7.15.1 you can also specify step counter for the ranges, so that you can get every Nth number or letter:</p>
<p>http://www.numericals.com/file[1-100:10].txt</p>
<p>http://www.letters.com/file[a-z:2].txt</p>
<p>If you specify URL without protocol:// prefix, curl will attempt to guess what protocol you might want. It will then default to HTTP but try other protocols based on often-used host name prefixes. For example, for host names starting with &#8220;ftp.&#8221; curl will assume you want to  speak FTP.</p>
<p>Curl  will  attempt  to re-use connections for multiple file transfers, so that getting many files from the same server will not do multiple connects / handshakes. This improves speed. Of course this is only done on files specified on a single  command  line  and  cannot  be  used<br />
between separate curl invokes.</p></blockquote>
<p>This is important as it helps measure the actual change being tested. A for loop, by creating a new process every loop, will fill up your test with &#8220;local&#8221; time. Using a single curl process eliminates this &#8211; which should allow you to see the results of your test in a more transparent manner.</p>
<p>For example, lets say you have a change that reduces page production time. Your not sure how long, so you decide to run 1000 tests. Eliminating a second from a 23 second tests is not 5 percent. While removing a second from a 6 second test, is almost 20%.</p>
]]></content:encoded>
			<wfw:commentRss>http://bashcurescancer.com/performance-testing-with-curl.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.332 seconds -->
