LevSelector.com |
Shell Scripting | Other pages |
• intro
• setting environment ( - ksh .profile, - tcsh .cshrc .login .aliases, - bash ) • wrappers ( - wrapper1, - db1, db2, db3, db4) • ftp • telnet • bash_event_designators |
• unix
• tcsh • Bourne sh_short • Bourne sh_tutorial |
intro | home - top of the page - |
A shell is a command interpreter. You type commands on the prompt. Shell
interprets them and passes further for the execution. Over the years unix
developers created many shells. Here are manpages for 5 most important
ones:
• www.engin.umich.edu/htbin/mangate?manpage=sh
- sh (bourne shell) - first, simpliest.
• www.engin.umich.edu/htbin/mangate?manpage=csh
- csh - from Berkley. Use tcsh instead of it.
• www.engin.umich.edu/htbin/mangate?manpage=ksh
- ksh (korn shell) - common, many programming features
• www.engin.umich.edu/htbin/mangate?manpage=tcsh
- tcsh - very good convenient shell (enchanced csh)
• www.engin.umich.edu/htbin/mangate?manpage=bash
- bash (born again shell) - main shell in the Linux world
• www.whereisit.com/shellscript/index2.html - shellscript.com - some good links
If you have any experience at all with Unix - you worked with one of those. The first one (Bourne shell) is very common - you can use it to write scripts. The C-shell (csh) is common, but should be avoided. You better use tcsh for command line editing, and bourne shell for installation scripts (read Tom Christiansen's article why csh (and tcsh) should not be used for writing shell scripts).
The last 3 scripts (ksh,tcsh, bash) are much more convenient to work with and you can use one of them as your command-line shell.
To find which shell you are running login to the prompt and use ps
command with no options.
Often $SHELL variable will show the current shell too.
Also in the /etc/passwd file you can see what is your default shell.
Here is what you can see on the prompt (your login name is "mylogin"):
> ps
PID TT STAT TIME COMMAND 6111 p0 Ss 0:00.06 -bash (bash) 6124 p0 R+ 0:00.01 ps > echo $SHELL /bin/bash > which bash /usr/local/bin/bash > which tcsh /bin/tcsh > which ksh /bin/ksh > which sh /bin/sh > which csh /bin/csh > which zsh /bin/zsh > whoami mylogin > cat /etc/passwd | grep mylogin mylogin:*:1487:102:,,,,:/home/mylogin:/bin/bash > |
• www.opennc.org/onlinepubs/7908799/xcu/sh.html
- using sh (includes vi-mode command line editing).
• http://codedata.box.sk/ghostrider/bash.tutor
- bash tutorial
• http://uracil.cmc.uab.edu/MolModLab/tutor/irix/basecmd.shtml
- intro into unix, includes shell scripting
2 ways to run shel scripts:
1.start a new shell (from command line or from a "shabang" line
(first line of your script)).
2.source the file (using source
or '.' (dot command)) - this way you
can change the enviromental variables in the currently running shell.
To force shell to echo commands:
use -v option (works with ksh, csh, tcsh & bash), for example:
tcsh -v myscript.sh
Using shell scripts:
I mostly use Perl instead of shell scripting. But you still need to
know at least a little bit of shell scripting for:
- writing very short scripts or installations scripts (see examples
below).
- setting environment (in .profile or .cshrc file)
- writing thin wrappers (see examples below)
Again, let me repeat main recommendations:
1. use tcsh, ksh or bash for your command-line editing.
2. use perl for scripting
3. If you need to write a shell script (for installation, for example)
- use bourne shell (sh) and NOT csh.
setting environment | home - top of the page - |
ksh: .profile
.profile
# ------------------------------------------
# .profile for ksh on Solaris # ------------------------------------------ if [ -f /somedir/setEnv.sh ]; then
set -o vi
ulimit -c 0 # LIMIT CORE DUMP SIZE rev=`uname -r`
# ------------------------------------------
PS1=`/usr/ucb/whoami`:'$PWD:'" "
HISTSIZE=1024
stty erase ^H # ------------------------------------------
# ------------------------------------------
# ------------------------------------------
export SYBASE=/opt/sybase PATH=$PATH:$HOME/bin:$HOME/util
CVSEDITOR=vi; export CVSEDITOR
alias l='ls -alF'
|
Settings for your xterm:
/usr/local/bin/dtterm -d 10.3.3.101:0.0
-fg black -bg white &
xterm -d daddypc:0.0 -fg green
-bg black &
xemacs -d daddypc:0.0 &
alias term='xterm -d daddypc:0.0 -fn -*-Fixed-Medium-R-*-*-*-120-75-75-*-*-ISO8859-1
-bg DarkCyan -fg White -geom 90x30 -cr red &'
alias term0='xterm -d daddypc:0.0 -fg black -bg white
&'
alias term1='xterm -d daddypc:0.0 -fn -*-Fixed-Medium-R-*-*-*-120-75-75-*-*-ISO8859-1
-bg black -fg LemonChiffon -geom 90x30 -cr red'
alias term2='xterm -d daddypc:0.0 -fn -*-Fixed-Medium-R-*-*-*-140-75-75-*-*-ISO8859-1
-bg black -fg LemonChiffon -geom 100x40 -cr red'
# export DISPLAY=daddypc:0.0
/usr/openwin/bin/xfontsel -d
daddypc:0.0 &
/usr/openwin/bin/xlsfonts
CTRL-(right-mouse-button)
tcsh: .cshrc
.login .aliases
.cshrc
# ------------------------------------------
# .cshrc file for tcsh # ------------------------------------------ if ( $?prompt ) then echo "Running cshrc..." endif if ($?DEBUGCSHRC) set echo umask 2 # figure out what os we're in
if ( $?prompt ) then
if ($?HAVEPATH == 0) then
if (-d /home/nysid10/sqllib/) then
setenv HOSTNAME `/bin/hostname`
if ($?SYBASE == 0) then
setenv SYBASE /opt/sybase
if ($?OPENWINHOME) then
|
.login
# ------------------------------------------
# .login file for tcsh # ------------------------------------------ if ( $?prompt ) then
if ($?DISPLAY == 0) then
if ($?MANPATH == 0) then
if ($?PRINTER) then
setenv EDITOR vi
|
.aliases
# ------------------------------------------
# .aliases file for tcsh # ------------------------------------------ if ( $?prompt ) then echo "Running aliases..." alias ls "\ls -F"
# ---- Find Magic :-) alias fpcgi 'find . -name "*.cgi" -print -exec grep "\!^" {}
\;'
# ---- Web development... alias GET "setenv REQUEST_METHOD GET"
# ---- Project Specific alias pf "cd ~someuser/somedir; pwd" alias DEVSERV "echo 'DEVSERV as mylogname'; \
alias sybdev "echo 'DEVSERV as mylogname'; \
alias iifiam="isql -U mylogname -P mylogname -S SERV2" alias cdcom "cd ~/dir/common; pwd"
alias london "rlogin -l mylogin serv.domain.com" # ---- Host specific if (`hostname` == "host1.dom1.com") then
alias psgrep 'ps -auxgww | grep $1'
# setting nice prompt (see www.engin.umich.edu/caen/faqs/setprompt.html ) if( ${?prompt} ) then
# --------------------
|
.bashrc
# --------------------
# .bashrc # -------------------- alias rm='rm -i' alias cp='cp -i' alias mv='mv -i' # ---- User specific aliases and functions # ---- Source global definitions
|
.bash_profile
# --------------------
# .bash_profile # -------------------- # ---- Get the aliases and functions
# ---- User specific environment and startup programs
ORACLE_BASE=/usr/local/oracle/8i/u01/app/oracle
BASH_ENV=$HOME/.bashrc
PATH=.:$HOME/util:$PATH:$HOME/bin:$ORACLE_HOME/bin:$JAVA_HOME/bin
|
writing thin wrappers | home - top of the page - |
Example: a thin wrapper running a perl script (note how syntax is different in 2 shells):
C-shell | Bourne shell |
#! /bin/csh
set mailTo='me@somedomain.com' set bindir='/home/some_directory' set log1file='/tmp/myfile.log' rm -f $log1file touch $log1file echo "Start time:" >> $log1file date >> $log1file $bindir/some_script.pl >>& $log1file
echo "Successful end time:" >> $log1file
|
#!/bin/sh
mailTo='Lev.Selector@gmail.com' bindir='/home/selecl/tests' log1file="/tmp/myfile.log" rm -f $log1file touch $log1file echo "Start time:" >> $log1file date >> $log1file $bindir/some_script.pl 1>>$log1file 2>>$log1file
echo "Successful end time:" >> $log1file
|
Example: a simple shell script I use to install tables and stored procedures into Sybase database.
#! /bin/csh
set dbServer="-S MY_DB_SERVER -U someuser -P somepasswd" isql $dbServer -ifile1.sp isql $dbServer -ifile2.sp isql $dbServer -ifile3.sp isql $dbServer -ifile4.sp |
Two small examples of including text into the script as "here doc" - or reading from a file (csh syntax):
$SYBASE/bin/isql -U$DB_USER -P$DB_PASSWD -S$SERVER -w300 <<EOF > $resultFile use $DATABASE go exec some_stored_procedure go EOF $SYBASE/bin/isql -U$DB_USER -P$DB_PASSWD -S$SERVER -w300 <<!
|
More sophisticated version - requires one parameter - a name of a text file with SQL to run
#!/usr/bin/sh
SERVER="MY_DB_SERVER" DATABASE="mydatabase" DB_USER=someuser DB_PASSWD=somepasswd if [ $# != 1 ]
file=$1 if [ ! -f $file ]
PATH="/bin:/usr/bin:/usr/local/bin:/usr/local/sybase/bin:someotherdirectories"
$SYBASE/bin/isql -U$DB_USER -P$DB_PASSWD -S$SERVER -w250 <<EOF
|
# db.sh - wrapper to prevent password from showing in ps:
#!/bin/sh
MYSQL="sql.txt" MYPASS="somepaswd" isql -S SOMESERVER -U someuser <<EOF
|
use somedatabase
go select * from sometable go |
writing thin wrappers | home - top of the page - |
Automating FTP:
#!/bin/sh
ftp -n <<EOF
|
#!/bin/sh
echo "open webprod
# Check FTP log to see if the file was retrieved okay if grep "^226" myftplog
|
By the way, you can always use Perl:
Example using Net::FTP
use Net::FTP;
$ftp = Net::FTP->new("some.host.name"); $ftp->login("anonymous","me@here.there"); $ftp->cwd("/pub"); $ftp->binary; $ftp->get("that.file"); $ftp->quit; |
Example using LWP::Simple
use LWP::Simple;
my $status = getstore('ftp://user:password@host/foo/file', 'localfile'); |
Automating telnet | home - top of the page - |
Sending telnet from a script - I don't know how to do this from a shell
script, because it doesn't have options for that. I think.
Usually people use something like remote shell (rsh)
http://www.engin.umich.edu/htbin/mangate?manpage=rsh
or kermit
http://www.columbia.edu/kermit/ckermit.html
http://www.columbia.edu/kermit/telnetd.html
http://www.columbia.edu/kermit/ck80.html
I would prefer to use a Perl script using NET::Telnet module from CPAN:
http://www.perldoc.com/cpan/Net/Telnet.html
Here are examples right from documentation of NET::Telnet :
use Net::Telnet ();
$t = new Net::Telnet (Timeout => 10, Prompt => '/bash\$ $/'); $t->open("sparky"); $t->login($username, $passwd); @lines = $t->cmd("/usr/bin/who"); # give command print @lines; # collect response # etc. |
my ($forecast, $t);
use Net::Telnet (); $t = new Net::Telnet; $t->open("rainmaker.wunderground.com"); ## Wait for first prompt and "hit return". $t->waitfor('/continue:.*$/'); $t->print(""); ## Wait for second prompt and respond with city code. $t->waitfor('/city code.*$/'); $t->print("BRD"); ## Read and print the first page of forecast. ($forecast) = $t->waitfor('/[ \t]+press return to continue/i'); print $forecast; exit; |
# -----------------------------------------------------------
# example checking mail on a pop server # ----------------------------------------------------------- my ($hostname, $line, $passwd, $pop, $username); $hostname = "your_destination_host_here"; $username = "your_username_here"; $passwd = "your_password_here"; use Net::Telnet (); $pop = new Net::Telnet (Telnetmode => 0); $pop->open(Host => $hostname, Port => 110); ## Read connection message. $line = $pop->getline; die $line unless $line =~ /^\+OK/; ## Send user name. $pop->print("user $username"); $line = $pop->getline; die $line unless $line =~ /^\+OK/; ## Send password. $pop->print("pass $passwd"); $line = $pop->getline; die $line unless $line =~ /^\+OK/; ## Request status of messages. $pop->print("list"); $line = $pop->getline; print $line; exit; |
BASH Event Designators | home - top of the page - |
- www.gnu.org/software/bash/manual/bashref.html
- Bash Reference
An event designator is a reference to a command line entry in the history list.
! | Start a history substitution, except when followed by a space, tab, the end of the line, `=' or `(' |
!n | Refer to command line n |
!-n | Refer to the command n lines back |
!! | Refer to the previous command. This is a synonym for `!-1' |
!string | Refer to the most recent command starting with string |
!?string[?] | Refer to the most recent command containing string. The trailing `?' may be omitted if the string is followed immediately by a newline |
^string1^string2^ | Quick Substitution. Repeat the last command, replacing string1 with string2. Equivalent to !!:s/string1/string2/ |
!# | The entire command line typed so far |