|
|
slmingol posted this in tips & tricks on October 1st, 2009, @ 10:35 am
Problem
Recently at my day job I’ve been having to go through some pretty old Bash scripts that I’ve basically inherited. As I’ve been going through them I’ve been seeing a lot of confusion as to the proper use of Bash’s export command. The major offense? Not really understand whether a particular variables needs to be exported, or not. So I thought I’d take a moment just to clarify when and when not to use export.
The export command has really only one true purpose. To mark and/or unmark variables (and functions) that you want to have automatically exported to environments of subsequently executed commands. So if you create a script that calls other commands, and you want to push variables into the environment of these commands, then you’ll want to use export.
Example #1 (without export)
For example, let’s say we have the following 2 scripts:
1
2
3
4
5
6
7
| #!/bin/bash
# script #1: parent.bash
var1="this was set by the parent shell script"
echo "inside $0 script: $var1"
./child.bash |
1
2
3
4
| #!/bin/bash
# script #2: child.bash
echo "inside $0 script: $var1" |
And when I run the script parent.bash I get this output:
1
2
3
4
5
| # output from parent.bash & child.bash (without export)
% ./parent.bash
inside ./parent.bash script: this was set by the parent shell script
inside ./child.bash script: |
Notice how the variable $var1, which was set in the parent.bash script, didn’t get displayed by the child.bash script? Now watch this example with the variable $var1 exported in the parent.bash script.
Example #2 (with export)
1
2
3
4
5
6
7
| #!/bin/bash
# script #1: parent.bash
export var1="this was set by the parent shell script"
echo "inside $0 script: $var1"
./child.bash |
1
2
3
4
| #!/bin/bash
# script #2: child.bash
echo "inside $0 script: $var1" |
And when we run parent.bash
1
2
3
4
5
| # output from parent.bash & child.bash (with export)
% ./parent.bash
inside ./parent.bash script: this was set my the parent shell script
inside ./child.bash script: this was set my the parent shell script |
Example #3 (un-exporting)
Export isn’t just a one trick pony. It can also unmark a previously exported variable.
…. Continue reading → [one-liner]: How to Use the Bash Shell’s export Command »»
slmingol posted this in tips & tricks on September 21st, 2009, @ 10:13 am
Background
I recently saw a post over on Linux Journal that discussed how to glean information about a system’s hard drive, such as its serial number, without having to actually open up the case and physically check it. So I thought I’d take the opportunity to write up a blog post with the specifics of how to do this under Fedora & CentOS, just so I’d have this info handy for future use.
BTW, I was able to accomplish this task several different ways, so this post will cover all the different ways that I could get this info.
Command #1: lshw
This is probably the best tool for getting at a system’s internals. First make sure it’s installed.
For our example you would run the command lshw -class disk:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| % lshw -class disk
*-disk
description: ATA Disk
product: HTS726060M9AT00
vendor: Hitachi
physical id: 0
bus info: scsi@0:0.0.0
logical name: /dev/sda
version: MH4O
serial: MRH403M4GS551Y
size: 55GiB (60GB)
capabilities: partitioned partitioned:dos
configuration: ansiversion=5 signature=cccdcccd
*-cdrom
description: DVD reader
product: UJDA755yDVD/CDRW
vendor: MATSHITA
physical id: 1
bus info: scsi@1:0.0.0
logical name: /dev/cdrom
logical name: /dev/cdrw
logical name: /dev/dvd
logical name: /dev/scd0
logical name: /dev/sr0
version: 1.71
capabilities: removable audio cd-r cd-rw dvd
configuration: ansiversion=5 status=nodisc |
The first section that’s returned is called -disk. Here’s you’ll see the vendor: Hitachi, the product number, HTS726060M9AT00, and my serial number: MRH403M4GS551Y.
Command #2: smartctl
The next tool that would give this type of info is called smartctl. It’s a tool that’s part of the smartmontool package. You may be familiar with the acronym S.M.A.R.T.. The acronym stands for: Self-Monitoring, Analysis, and Reporting Technology. This is a standard that most modern disks have in which vital statistics about a disk drive are provided through a standard API. Here’s how to install it.
1
| yum install smartmontools |
…and once installed you can use the bundled in tool smartctl like so:
…. Continue reading → [one-liner]: Determining a Hard Drive’s Manufaturer Under Fedora 10 & CentOS 5 »»
slmingol posted this in tips & tricks on August 25th, 2009, @ 1:12 am
Background
I recently worked a problem in a previous post where it wasn’t clear which version of the command nohup was getting used. The version that was built into the C-shell interpreter, or the executable sitting under /usr/bin/nohup. This brought up an interesting point, how do you know what commands are builtins to the shell itself?
Enter the commands: builtins and enable
These are 2 commands that I’d never even heard of until I started doing research for this post. They both basically do the same thing. They show you all the builtin commands for a particular shell, builtins for C-shell, and enable for Bourne Shell.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # C-shell builtins
#NOTE: run this command within a C-shell (aka. csh or tcsh)
% csh
% builtins
: @ alias alloc bg bindkey break
breaksw builtins case cd chdir complete continue
default dirs echo echotc else end endif
endsw eval exec exit fg filetest foreach
glob goto hashstat history hup if jobs
kill limit log login logout ls-F nice
nohup notify onintr popd printenv pushd rehash
repeat sched set setenv settc setty shift
source stop suspend switch telltc termname time
umask unalias uncomplete unhash unlimit unset unsetenv
wait where which while |
1
2
3
4
5
6
7
| # Bourne Again Shell builtins
#NOTE: run this command within Bourne Again Shell (aka. bash)
% bash
% enable | cut -d" " -f2 | sed -e :a -e '$!N;s/\n/ /;ta'
. : [ alias bg bind break builtin caller cd command compgen complete continue declare dirs disown echo enable eval exec exit export false fc fg getopts hash help history jobs kill let local logout popd printf pushd pwd read readonly return set shift shopt source suspend test times trap true type typeset ulimit umask unalias unset wait |
NOTE: The command is enable. I’m simply running the output of enable through this cut & sed filter so that the output of enable is more concise for this example.
nohup
As you can see, by looking at the output from builtins, the command nohup is listed there, which means that C-shell has it’s own implementation of nohup. Looking at the output from enable, you can see that Bourne Shell, doesn’t include it’s own builtin for nohup, so it would use /usr/bin/nohup. Pretty simple, eh?
NOTE: For further details regarding my one-liner blog posts, check out my one-liner style guide primer.
slmingol posted this in tutorials on August 24th, 2009, @ 3:39 am
Background
I listen to a lot of tech podcasts, and a while back I started not being able to keep up with all of them on a weekly basis. The thought of dropping some of them to make room wasn’t really an option. So I started fast forwarding through some of the “dead air” in an attempt to speed up their playback. This got old pretty quickly. Being a pretty tech. savvy person, I thought there had to be a programmatic way to solve my dilema. I initially latched on to the idea that a program could remove/compress this “dead air” automatically so that its effect would be minimized. This would in theory condense a 1 hour podcast to something less than an hour. Although my final solution didn’t exactly go this route, there was enough of a kernel of an idea that ultimately led me to a workable solution.
Initial Concept
The biggest irony in my solution? it came while I was listening to a podcast, The Linux Outlaws. I think it was this episode. One of the listeners had either emailed or called in with the crux of the solution that I ultimately utilized to get exactly what I wanted. The key concept that this listener had mentioned was changing the tempo of an audio file. Now I’m no audiophile but I had heard the term tempo before, I just never really put much thought into exactly what it was. This listener claimed that you could increase/decrease the tempo of an audio file but still maintain its listenability. My previous experience with speeding up audio, was taking 45 and 78 RPM records and cranking up the speed dial on my turntable so that they sounded like Alvin and the Chimpmunks, an effect called resampling.
Subsequent googling turned up this Wikipedia article. In a nutshell, tempo is similar to the beats per minute (bpm) in music. So what we’re doing when we manipulate the tempo, is we’re increasing/decreasing the beats per minute, but we’re maintaining the pitch of those beats. The key component in maintaining the original quality of an audio file, is to maintain its pitch. Increasing the pitch is the effect you are hearing when you simply turn up the playback speed, as in the turntable example.
mp3faster
So how do you affect the tempo without messing with the pitch? Several tools can do this. Audacity is one of them. However I wanted to develop a script that would do this, because I ultimately wanted to have my podcatching software, bashpodder, automatically speed up all the MP3 files that it downloads. Some more googling turned up exactly what I was looking for, a page on the gPodder wiki” about time stretching . This wiki page had a script on it called mp3faster that did exactly what I wanted. The centerpiece to this script is a command-line tool called soundstretch, which is part of a suite of tools called SoundTouch. The mp3faster script was originally developed to run on Ubuntu, I’ve since modified it with the following enhancements:
- runs on Redhat Distros (RHEL, Fedora, & CentOS)
- improved method for converting the initial MP3 file to WAV
- improved the copying of the original MP3′s id3 tags over to the new MP3 file
- variablized the tempo so that it can be passed in as a command line arguement
- force the replacement of the original MP3 file with the newly modified version
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| % more mp3faster.bash
#!/bin/bash
# mp3faster - script for making mp3 playback faster with soundstretch
#
# debian/ubuntu package requirements
# apt-get install mpg321 soundstretch lame libid3-3.8.3-dev
#
# rhel/centos/fedora package requirements
# yum install mpg321 soundtouch lame id3lib
#
# sample usage for converting all mp3 files in a directory structure:
# find -name "*.mp3" -print0 | xargs -0 -i mp3faster {}
#
# decode mp3 to wav file
#mpg321 --wav "$1.wav" "$1"
# the above decoding technique doesn't always work, and can sometimes
# create a wav file that plays back too fast. Seems to happen with mp3 files that
# have a low bitrate (< 80kbps). Using the lame alternative below get's around this.
# alternative #1 to decoding an mp3 to wav
lame --decode "$1" "$1.wav"
# alternative #2 to decoding an mp3 to wav
# mpg321 -b 10000 -s -r 44100 $1 | sox -t raw -r 44100 -s -w -c2 - "$1.wav"
# process file with soundstretch
#soundstretch "$1.wav" "$1.fast.wav" -tempo=+65
soundstretch "$1.wav" "$1.fast.wav" -tempo=+$2
# encode mp3 file
lame --preset fast medium "$1.fast.wav" "$1.2.mp3"
# copy id3 tags from old file
id3cp -1 "$1" "$1.2.mp3"
# remove temp files
rm "$1.wav" "$1.fast.wav"
# rename original mp3 file to .bak extension
# mv "$1" "$1.bak"
# rename processed mp3 file to original name
mv -f "$1.2.mp3" "$1" |
Prerequisites
To install the prerequisite software on my CentOS 5 system, I used the following command:
…. Continue reading → Speeding up the Playback of Audio Podcasts »»
slmingol posted this in tips & tricks on July 10th, 2009, @ 2:08 am
I’ve been working with UNIX operating systems for 20+ years and I’m still amazed at how much I still don’t know about it. Recently at work I came across a script (Bourne) that made use of the wait command. Now if someone had asked me if a command like this existed I would probably have guessed yes, so I wasn’t completely shocked by it, but I was kinda surprised that I had never seen it actually used anywhere in the wild.
The wait command gives you the ability to block a script on the termination of another process or list of processes. This can come in handy when you want to make sure a program finished before you’re script moves on. Specifically for a program where it runs as a backgrounded process.
I like examples so here are a couple that demonstrate how wait works.
Example 1
1
2
3
4
5
6
7
8
9
10
| # wait with a process id
# run the sleep command for 15 seconds backgrounded
% sleep 15 &
[1] 8546
# wait for sleep's process id ($!) to finish, and then echo "hi"
% wait $! && echo "hi"
[1]+ Done sleep 15
hi |
Example 2
Additionally you can give wait the job id (%1, %2, etc.) instead.
1
2
3
4
5
6
7
| # wait with a job id
% sleep 15 &
[1] 8551
% wait %1 && echo "hi"
[1]+ Done sleep 15
hi |
Example 3
You can also drop the process id entirely if the wait command occurs right after the backgrounded command.
1
2
3
4
5
6
7
| # wait without any argument
% sleep 10 &
[1] 8552
% wait && echo "hi"
[1]+ Done sleep 10
hi |
Example 4
Finally you can tell wait to wait on more than one process.
1
2
3
4
5
6
7
8
9
10
| # wait on 2 processes
% sleep 10 &
[1] 8570
% sleep 10 &
[2] 8571
% wait %1 %2 && echo "hi"
[1]- Done sleep 10
[2]+ Done sleep 10
hi |
For more information about the wait command check out the wait section of the Bash FAQ. Check out more about special variables in Bash.
NOTE: For further details regarding my one-liner blog posts, check out my one-liner style guide primer.
slmingol posted this in tips & tricks on June 20th, 2009, @ 12:36 am
I do this command from time to time so I wanted to just jot it down so I didn’t have to go recreating every 6 months that I seem to need it. The setup for this example is that I had created a bunch of screenshots named ss#.png and I wanted to rename them to ss_centos5_raid_setup_#.png, where “#” is a numeric value.
Initial Set of Files
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # Here what the directory looks like to start
% ls
ss01.png
ss02.png
ss03.png
ss04.png
ss05.png
ss06.png
ss07.png
ss08.png
ss09.png
ss10.png
ss11.png
ss12.png
ss13.png |
New File Names
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # and here's what our command will generate for new names
# NOTE: this instance of the command is for debug purposes only
#
% for old in *; do new="`echo $old | sed 's/ss/ss_centos5_raid_setup_/'`"; echo $new; done
ss_centos5_raid_setup_01.png
ss_centos5_raid_setup_02.png
ss_centos5_raid_setup_03.png
ss_centos5_raid_setup_04.png
ss_centos5_raid_setup_05.png
ss_centos5_raid_setup_06.png
ss_centos5_raid_setup_07.png
ss_centos5_raid_setup_08.png
ss_centos5_raid_setup_09.png
ss_centos5_raid_setup_10.png
ss_centos5_raid_setup_11.png
ss_centos5_raid_setup_12.png
ss_centos5_raid_setup_13.png |
Moving $old to $new
1
2
| # and here's the final command that will do all the lifting
for old in *; do new="`echo $old | sed 's/ss/ss_centos5_raid_setup_/'`"; mv $old $new; done |
The general form of this command
1
| for old in *; do new="`echo $old | sed 's/<old prefix>/<new prefix>/'`"; mv $old $new; done |
NOTE: For further details regarding my one-liner blog posts, check out my one-liner style guide primer.
|