Difference between revisions of "Unix/Linux"

From dbawiki
Jump to: navigation, search
(Troubleshoot wireless network problems)
(Use sed to delete the first line of a file or command output printing from the second line onwards)
 
(82 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
* [http://hyperpolyglot.org/unix-shells#var-expansion Good shell comparison including variable expansion - hyperpolyglot.org]
 +
* [http://pubs.opengroup.org/onlinepubs/9699919799/utilities/toc.html Shell coding standards - opengroup.org]
 
* [http://aix4admins.blogspot.be aix4admins]
 
* [http://aix4admins.blogspot.be aix4admins]
 
* [http://linuxgazette.net/issue55/okopnik.html The Deep, Dark Secrets of Bash]
 
* [http://linuxgazette.net/issue55/okopnik.html The Deep, Dark Secrets of Bash]
Line 6: Line 8:
 
* [http://www.grymoire.com/unix/Quote.html Unix quoting from from Bruce Barnett (grymoire)]
 
* [http://www.grymoire.com/unix/Quote.html Unix quoting from from Bruce Barnett (grymoire)]
 
* [http://www.mpi-inf.mpg.de/departments/rg1/teaching/unixffb-ss98/quoting-guide.html Another excellent quoting tutorial]
 
* [http://www.mpi-inf.mpg.de/departments/rg1/teaching/unixffb-ss98/quoting-guide.html Another excellent quoting tutorial]
 +
* [http://aix4admins.blogspot.be/2015/02/snapshot-fs-snapshot-snapshot-is-state.html AIX snapshot technology]
 
* [[RaspberryPi]]
 
* [[RaspberryPi]]
 
* [[SSH]]
 
* [[SSH]]
* [http://www.anattatechnologies.com/q/2013/04/multiuser-screen/ Screen sharing from Unix]
+
* [http://www.anattatechnologies.com/q/2013/04/multiuser-screen/ Screen sharing from Unix using screen]
 +
* [https://robots.thoughtbot.com/a-tmux-crash-course Screen sharing from Unix using tmux]
 +
* [http://www.csb.yale.edu/userguides/wordprocess/vi-summary.html Handy ex and vi reference]
 +
* [[Fedora install for my own purposes]]
  
===Use sed to repeat characters===
+
===How to automatically download and process email attachments from Gmail===
echo an '=' sign then use the loop feature of sed to run round a loop a further 79 times replacing what you've got with the same thing plus and extra one!
+
==== Useful references====
 +
* [http://www.courier-mta.org/maildrop/maildrop.html maildrop]
 +
* [http://www.wonkity.com/~wblock/docs/html/maildrop.html Using maildrop As A Mail Delivery Agent (MDA)]
 +
* [http://manpages.ubuntu.com/manpages/trusty/man7/maildropex.7.html .mailfilter examples]
 +
* [https://www.axllent.org/docs/view/gmail-pop3-with-fetchmail/ Setting up fetchmail with Gmail]
 +
* [https://www.linode.com/docs/email/clients/using-fetchmail-to-retrieve-email/ Using Fetchmail to Retrieve Email]
 +
 
 +
Eventually, after months of trying different things, came up with this combination of tools that worked very well.
 +
====Install tools====
 
<pre>
 
<pre>
echo "=" | sed -e :a -e 's/^=\{1,79\}$/&=/;ta'
+
sudo dnf -y install fetchmail maildrop uudeview openssl
 
</pre>
 
</pre>
===double hash and double percent in shell variables to trim off characters from variables===
+
* Set Gmail account up for POP and disable IMAP
<nowiki>#</nowiki>  - trims everything from the start of line till the FIRST occurrence of following character<br />
+
====Configure fetchmail====
<nowiki>##</nowiki> - trims everything from the start of line till the LAST occurrence of following character<br />
+
This is the part that talks to Gmail and downloads the emails to the local machine.
%  - trims everything from the end of line backwards till the FIRST occurrence of following character<br />
 
%% - trims everything from the end of line backwards till the LAST occurrence of following character
 
 
<pre>
 
<pre>
FILENAME="/home/bey9at77/hello.txt"
+
vi ~/.fetchmailrc
FILE_STUB1=${FILENAME##*/}
+
 
FILE_STUB=${FILE_STUB1%.*}
+
set postmaster "<username>"
echo $FILE_STUB
+
#set daemon 600
hello
+
poll pop.gmail.com with proto POP3
 +
    user "[email protected]" there with password '<password>' is <username> here options ssl nokeep
 +
    mda "/usr/bin/maildrop .mailfilter"
 +
#   sslcertfile /etc/ssl/certs/ca-bundle.crt
 
</pre>
 
</pre>
 +
If fetchmail complains about ssl certificates, try specifying wherein is with the sslcertfile line
 +
==== Configure maildrop====
 +
<pre>
 +
maildirmake maildrop
 +
maildirmake backup
  
===split variable (eg. filename) into separate variables using set===
+
vi ~/.mailfilter
<pre>
+
 
FILENAME="split_this_into_bits"
+
LOGFILE = "/home/dbahawk/maildrop/maildrop.log"
set $(echo ${FILENAME} | sed 's/_/ /g')
+
DEFAULT="$HOME/maildrop"
echo $4 $3 $2 $1
+
 
bits into this split
+
# keep a copy
 +
cc backup
 +
`cd backup/new && rm -f dummy \`ls -t | sed -e 1,50d\``
 +
 
 +
if (/^To:.*getmail@...\.dnsalias\.org$/)
 +
  {
 +
        to Maildir/getmail/
 +
  }
 +
 
 +
#if (/^To:.*dbahawk/)
 +
#  {
 +
#        to maildrop
 +
#  }
 +
 
 +
if (/^To:.*dbahawk/)
 +
    dotlock "auto.lock" {
 +
    to "|uudeview -c -i"
 +
}
 
</pre>
 
</pre>
===Centre align text on a line in bash shell===
+
Not really sure why this filter is not working properly. The cc works but the To: check doesn't. So I have a shell that runs separately to process the emails in the backup mail directory.
Doesn't work in Korn shell due to %*s
+
 
 +
====uudeview====
 +
This is a clever program that can extract attachments from emails and put them in a directory of you choosing.<br />
 +
This shell runs from cron at regular intervals to run the whole process
 
<pre>
 
<pre>
#COLUMNS=$(tput cols)   # width of the current window
+
#!/usr/bin/ksh
COLUMNS=80
+
 
title="Hello world!"
+
# fetch any new mail from Gmail (uses .fetchmailrc)
printf "%*s\n" $(((${#title}+$COLUMNS)/2)) "$title"
+
# fetchmail log is $HOME/maildrop/maildrop.log
 +
fetchmail -d0
 +
 
 +
# fetchmail uses maildrop as mda (uses .mailfilter) to save messages to a maildir.
 +
# this is not working correctly but still copies the messages to backup
 +
 
 +
# pull out the attachments and send them to the incoming directory for the collector to process when it wakes up
 +
uudeview -c -i -p ~/Downloads/dbahawk_forward backup/new/*
 +
</pre>
 +
 
 +
===Use sed to repeat characters===
 +
echo an '=' sign then use the loop feature of sed to run round a loop a further 79 times replacing what you've got with the same thing plus and extra one!
 +
<pre>
 +
echo "=" | sed -e :a -e 's/^=\{1,79\}$/&=/;ta'
 
</pre>
 
</pre>
and as a one-liner
+
 
 +
===Convert between lower and upper case using ansi standard===
 +
This way should be portable and give predictable results
 
<pre>
 
<pre>
printf "%*s\n" $(( ( $(echo $* | wc -c ) + 80 ) / 2 )) "$*"
+
LOWER_SID=$(echo "${SID}" | tr '[:upper:]' '[:lower:]')
 +
UPPER_SID=$(echo "${SID}" | tr '[:lower:]' '[:upper:]')
 
</pre>
 
</pre>
This works in Korn shell...
+
===Use sed to delete the first line of a file or command output printing from the second line onwards===
 +
Actually deceptively simple. Example remove the header from df output.
 
<pre>
 
<pre>
TITLE="$1"
+
df -k | sed 1d
LINEWIDTH=80
+
 
 +
or more formally
  
LPAD=$(((${#TITLE}+$LINEWIDTH)/2))
+
df -k | sed -e '1,1d'
printf %${LPAD}s "$TITLE"
+
</pre>
 +
As a useful extension, suppose TO_DATA_DIR contains multiple directories, this will total the free space for all relevant filesystems<br />
 +
This one is specific to AIX, for other Unixes and Linux, use $4 instead of $3.
 +
<pre>
 +
SPACE_AVAILABLE=$(df -k $TO_DATA_DIR | sed 1d | awk 'BEGIN {i=0} {i=i+$3} END {print i}')
 
</pre>
 
</pre>
  
===Right justify text (or repeat characters) on a line with leader dots!===
+
===Use sed to munge a controlfile into submission!===
 +
* delete comment lines
 +
* delete all lines after the one starting with a semicolon
 +
* delete all blank lines
 +
* change reuse to set
 +
* change archivelog (with word boundaries) to noarchivelog
 +
* change old sid to new sid
 
<pre>
 
<pre>
function rpadwait {
+
sqlplus -s / as sysdba<<'EOSQL' >/dev/null
    text=$1
+
alter database backup controlfile to trace as '/tmp/regenerate_controlfile.sql' reuse resetlogs;
# -------------------------
+
EOSQL
# suppress newline for echo
+
OLDSID='PROD'
# -------------------------
+
NEWSID='TEST'
N=
+
sed  -e '/^--/d' -e '/^\;/q' -e '/^ *$/d' -e 's/REUSE/SET/' -e 's/\<ARCHIVELOG\>/NOARCHIVELOG/' -e 's/\"'${OLDSID}'\"/\"'${NEWSID}'\"/' /tmp/regenerate_controlfile.sql
C=
+
</pre>
if echo "\c" | grep c >/dev/null 2>&1; then
+
===Find all files where a certain text does not exist===
    N='-n'
+
Mostly we want to search for files containing a particular string but how to find those files that do not contain some text.<br />
else
+
Using xargs instead of -exec forces the filename to be printed. -H should do this but doesn't seem to in this case.
    C='\c'
+
<pre>
fi
+
find . -name "*cfg" | xargs grep -H -c TO_CV_HOST {} \; | grep ':0$' | cut -d: -f1
 +
</pre>
  
 
+
===Use tar and gzip to copy files more efficiently across network between hosts===
    echo ${N} "${text}${C}" | sed -e :a -e 's/^.\{1,80\}$/&\./;ta'
+
From the destination server, this will connect to the source, tar up each file and pull it back to the current server
}
+
<pre>
 +
ssh oracle@hn5211 "cd /oracle/ora_data4/iten3/ && tar -cf - . | gzip " | ( cd /oracle/ora_data2/iten/ && gunzip -c | tar -xvf - . )
 
</pre>
 
</pre>
  
===cron jobs not submitted - daemon run out of child processes?===
+
===double hash and double percent in shell variables to trim off characters from variables===
Sometimes have problems with NFS mounts and this causes cron jobs to hang. If they are scheduled to run regularly, eventually cron will no longer be able to start any more jobs.<br />
+
<nowiki>#</nowiki>  - trims everything from the start of line till the FIRST occurrence of following character (abstemious) :-)<br />
* Check the cron log '''/var/adm/cron/log''' to see if there are any errors or other messages around the time the jobs should run.
+
<nowiki>##</nowiki> - trims everything from the start of line till the LAST occurrence of following character (greedy)<br />
If cron has hit its process limit (default 100), it will try again after a number of seconds (default 60).<br />
+
%  - trims everything from the end of line backwards till the FIRST occurrence of following character (abstemious)<br />
Both the number of jobs and wait time are configured in the file '''/var/adm/cron/queuedefs'''. If it is unusual for cron to be running so many jobs, you can check the process table to view the jobs cron has created. These jobs will have parent process id (PPID) of the cron daemon.<br />
+
%% - trims everything from the end of line backwards till the LAST occurrence of following character (greedy)
 
<pre>
 
<pre>
$ ps -ef | grep cron | grep -v grep
+
FILENAME="/home/bey9at77/hello.txt"
    root  6750314        1  0  Apr 24      -  3:39 /usr/sbin/cron
+
FILE_STUB1=${FILENAME##*/}
solax025:root[/home/root]# ps -T 6750314
+
FILE_STUB=${FILE_STUB1%.*}
      PID    TTY  TIME CMD
+
echo $FILE_STUB
  6750314      -  3:39 cron
+
hello
21168296      -  0:00    \--bsh
+
FILE_EXT=${FILENAME##*.}
58982414      -  0:00        \--sadc
+
echo $FILE_EXT
 +
txt
 
</pre>
 
</pre>
In this example, we only have 1 job running
+
or<br />
 +
<nowiki>#</nowiki> - remove prefix reluctantly<br />
 +
<nowiki>##</nowiki> - remove prefix greedily<br />
 +
% - remove suffix reluctantly<br />
 +
%% - remove suffix greedily<br />
 +
<pre>
 +
words="do.re.mi"
 +
 
 +
echo ${words#*.}
 +
 
 +
echo ${words##*.}
 +
 
 +
echo ${words%.*}
  
===Find long-running processes with a cron job===
+
echo ${words%%.*}
Processes running longer than 24 hours have a date instead of a start time...
 
<pre>
 
58 08,14 * * * /home/ibmtools/scripts/oracle/dosh -vc "ps -ef|grep 'ibmtools/scripts/oracle'|perl -nae 'print if \$F[4] !~/:/'" >/tmp/lrp.txt; [[ $(grep -c ibmtools /tmp/lrp.txt) -ne 0 ]] && cat /tmp/lrp.txt|mailx -s '*** long running processes - please check ***' [email protected]
 
 
</pre>
 
</pre>
  
===Process command line arguments in shell===
+
===The best shell script ever. An example of how scripting should be done===
Borrowed from Mozilla Firefox installer
+
It was written by someone at Oracle. Unfortunately (s)he did not put any author comment in it. Also unfortunately I cannot show it here as it is protected behind Oracles support website.<br />
 +
If you have an Oracle Metalink id, you can get the complete script [https://support.oracle.com/epmos/faces/DocumentDisplay?id=949322.1 here]<br />
 +
Here is a snippet of a function that demonstrates proper commenting and a very good style.<br >
 +
The script is called physru.sh and upgrades an Oracle database in a rolling upgrade fashion by using a physical standby.<br />
 +
There are 4500 lines in the full script but it is so easy to read and understand because of the way it's written, it's like a breath of fresh air. Well done whoever you are!
 
<pre>
 
<pre>
## Command line arg defaults
+
###############################################################################
##
+
# NAME:        wait_mrp_active
moz_debug=0
+
#
moz_debugger=""
+
# DESCRIPTION:
moz_debugger_args=""
+
#  Wait for $MRP_START_TIMEOUT minutes to confirm that the MRP is active.  If
 +
#  we can't detect an active MRP, abort the script with an error.
 
#
 
#
##
+
# INPUT(S):
## Parse the command line
+
#  Arguments:
##
+
#    $1: database user
while [ $# -gt 0 ]
+
#    $2: user password
do
+
#     $3: tns service name
   case $1 in
+
#     $4: database unique name
    -g | --debug)
+
#
      moz_debug=1
+
#   Globals:
      shift
+
#    None
      ;;
+
#
     -d | --debugger)
+
# RETURN:
      moz_debugger=$2;
+
#  None
      if [ "${moz_debugger}" != "" ]; then
+
#
shift 2
+
###############################################################################
       else
+
wait_mrp_active()
        echo "-d requires an argument"
+
{
        exit 1
+
  display "confirming media recovery is running"
      fi
+
   l_wma_status=1
      ;;
+
  l_wma_curtime=`perl -e 'print int(time)'`
    -a | --debugger-args)
+
  l_wma_exptime=`expr $MRP_START_TIMEOUT "*" 60`
      moz_debugger_args=$2;
+
  l_wma_maxtime=`expr $l_wma_curtime + $l_wma_exptime`
      if [ "${moz_debugger_args}" != "" ]; then
+
  while [ "$l_wma_curtime" -lt "$l_wma_maxtime" ]
shift 2
+
  do
      else
+
     is_mrp_running $1 $2 $3 $4
        echo "-a requires an argument"
+
    if [ "$?" -gt "0" ]; then
        exit 1
+
      l_wma_status=0
      fi
+
       break
      ;;
+
    fi
    *)
+
 
      break;
+
    sleep $MRP_START_INTERVAL
      ;;
+
    l_wma_curtime=`perl -e 'print int(time)'`
  esac
+
  done
done
+
  chkerr $l_wma_status "could not detect an active MRP after $MRP_START_TIMEOUT minutes"
#
+
}
##
+
</pre>
## Program name given in $1
+
 
##
+
===split variable (eg. filename) into separate variables using set===
if [ $# -gt 0 ]
+
<pre>
then
+
FILENAME="split_this_into_bits"
MOZ_PROGRAM=$1
+
set $(echo ${FILENAME} | sed 's/_/ /g')
shift
+
echo $4 $3 $2 $1
 +
bits into this split
 +
</pre>
 +
===Centre align text on a line in bash shell===
 +
Doesn't work in Korn shell due to %*s
 +
<pre>
 +
#COLUMNS=$(tput cols)   # width of the current window
 +
COLUMNS=80
 +
title="Hello world!"
 +
printf "%*s\n" $(((${#title}+$COLUMNS)/2)) "$title"
 +
</pre>
 +
and as a one-liner
 +
<pre>
 +
printf "%*s\n" $(( ( $(echo $* | wc -c ) + 80 ) / 2 )) "$*"
 +
</pre>
 +
This works in Korn shell...
 +
<pre>
 +
TITLE="$1"
 +
LINEWIDTH=80
 +
 
 +
LPAD=$(((${#TITLE}+$LINEWIDTH)/2))
 +
printf %${LPAD}s "$TITLE"
 +
</pre>
 +
 
 +
===Right justify text (or repeat characters) on a line with leader dots!===
 +
<pre>
 +
function rpadwait {
 +
    text=$1
 +
# -------------------------
 +
# suppress newline for echo
 +
# -------------------------
 +
N=
 +
C=
 +
if echo "\c" | grep c >/dev/null 2>&1; then
 +
    N='-n'
 +
else
 +
    C='\c'
 
fi
 
fi
##
+
 
## Program not given, try to guess a default
+
 
##
+
    echo ${N} "${text}${C}" | sed -e :a -e 's/^.\{1,80\}$/&\./;ta'
if [ -z "$MOZ_PROGRAM" ]
+
}
then
+
</pre>
##
+
 
## Try this script's name with '-bin' appended
+
===cron jobs not submitted - daemon run out of child processes?===
##
+
Sometimes have problems with NFS mounts and this causes cron jobs to hang. If they are scheduled to run regularly, eventually cron will no longer be able to start any more jobs.<br />
if [ -x "$MOZ_DEFAULT_NAME" ]
+
* Check the cron log '''/var/adm/cron/log''' to see if there are any errors or other messages around the time the jobs should run.
then
+
If cron has hit its process limit (default 100), it will try again after a number of seconds (default 60).<br />
MOZ_PROGRAM=$MOZ_DEFAULT_NAME
+
Both the number of jobs and wait time are configured in the file '''/var/adm/cron/queuedefs'''. If it is unusual for cron to be running so many jobs, you can check the process table to view the jobs cron has created. These jobs will have parent process id (PPID) of the cron daemon.<br />
##
 
## Try mozilla-bin
 
##
 
elif [ -x "$MOZ_APPRUNNER_NAME" ]
 
then
 
MOZ_PROGRAM=$MOZ_APPRUNNER_NAME
 
fi
 
fi
 
#
 
#
 
##
 
## Make sure the program is executable
 
##
 
if [ ! -x "$MOZ_PROGRAM" ]
 
then
 
moz_bail "Cannot execute $MOZ_PROGRAM."
 
fi
 
#
 
</pre>
 
 
 
===Carry XWindows settings across sessions===
 
 
<pre>
 
<pre>
# ----------------------
+
$ ps -ef | grep cron | grep -v grep
# push XWindows settings
+
    root  6750314        1  0  Apr 24      - 3:39 /usr/sbin/cron
# ----------------------
+
solax025:root[/home/root]# ps -T 6750314
[[ "`uname`" == "SunOS" ]] && PATH=/usr/openwin/bin:$PATH
+
      PID    TTY  TIME CMD
WHOAMI=`id | awk -F')' '{print $1}' | awk -F'(' '{print $2}'`
+
  6750314      - 3:39 cron
xauth list > /tmp/xauth_list_$WHOAMI
+
21168296      - 0:00    \--bsh
chmod 777 /tmp/xauth_list_$WHOAMI
+
58982414      - 0:00        \--sadc
 +
</pre>
 +
In this example, we only have 1 job running
  
echo $DISPLAY > /tmp/xdisplay_$WHOAMI
+
===Find long-running processes with a cron job===
chmod 777 /tmp/xdisplay_$WHOAMI
+
Processes running longer than 24 hours have a date instead of a start time...
 +
<pre>
 +
58 08,14 * * * /home/ibmtools/scripts/oracle/dosh -vc "ps -ef|grep 'ibmtools/scripts/oracle'|perl -nae 'print if \$F[4] !~/:/'" >/tmp/lrp.txt; [[ $(grep -c ibmtools /tmp/lrp.txt) -ne 0 ]] && cat /tmp/lrp.txt|mailx -s '*** long running processes - please check ***' [email protected]
 
</pre>
 
</pre>
===Cross-platform version of whoami===
+
 
 +
===Process command line arguments in shell===
 +
Borrowed from Mozilla Firefox installer
 
<pre>
 
<pre>
WHOAMI=`id | awk -F')' '{print $1}' | awk -F'(' '{print $2}'`
+
## Command line arg defaults
</pre>
+
##
===Set terminal title from command line===
+
moz_debug=0
Put something like this in the .profile<br />
+
moz_debugger=""
-n    do not output the trailing newline<br />
+
moz_debugger_args=""
-e    enable interpretation of backslash escapes<br />
+
#
|0    sets title of window and icon<br />
+
##
|1    sets title of icon only<br />
+
## Parse the command line
|2     sets title of window only<br />
+
##
<pre>
+
while [ $# -gt 0 ]
echo -en "\033]0;`hostname`\007"
+
do
</pre>
+
  case $1 in
<pre>
+
    -g | --debug)
echo -en "\033]2;`hostname`\007"
+
      moz_debug=1
</pre>
+
      shift
 
+
      ;;
===Return elements of an array in Korn shell===
+
     -d | --debugger)
From [http://unix.stackexchange.com/questions/188202/processing-output-from-an-sqlite-db-into-a-ksh-array-with-spaces here]<br />
+
      moz_debugger=$2;
Could be used to separate the columns of an SQL select when returning to the shell<br />
+
      if [ "${moz_debugger}" != "" ]; then
This approach eliminates the need to put quotes around text with spaces in it.
+
shift 2
<pre>
+
      else
echo $KSH_VERSION
+
        echo "-d requires an argument"
x="Red,Yellow is a color,Blue"
+
        exit 1
oIFS=$IFS
+
      fi
IFS=,
+
      ;;
y=($x)
+
    -a | --debugger-args)
IFS=$oIFS
+
      moz_debugger_args=$2;
echo ${y[1]}
+
      if [ "${moz_debugger_args}" != "" ]; then
</pre>
+
shift 2
 
+
      else
===A decent Unix Prompt===
+
        echo "-a requires an argument"
<pre>
+
        exit 1
export PS1="`uname -n`:`whoami`[\${PWD}]# "
+
      fi
or
+
      ;;
export PS1='($?) $'ORACLE_SID" "`whoami`"@"`uname -n`":"'$'PWD"> "
+
    *)
export EDITOR=vi
+
      break;
</pre>
+
      ;;
 
+
  esac
===Mount a website (or any other remote resource) locally using WebDav===
+
done
Redhat/CentOS
+
#
<pre>
+
##
yum install fuse-davfs2
+
## Program name given in $1
or
+
##
yum install wdfs.x86_64
+
if [ $# -gt 0 ]
</pre>
+
then
Debian
+
MOZ_PROGRAM=$1
<pre>
+
shift
apt-get install davfs2
+
fi
</pre>
+
##
then...
+
## Program not given, try to guess a default
<pre>
+
##
sudo mkdir /mnt/webdav  # or whatever you'd like to call the directory
+
if [ -z "$MOZ_PROGRAM" ]
sudo mount.davfs [-o option[,option]...] device mount_point
+
then
</pre>
+
##
In man's terms, that last line would translate to:
+
## Try this script's name with '-bin' appended
<pre>
+
##
id  #suppose this returns uid=501 and gid=502
+
if [ -x "$MOZ_DEFAULT_NAME" ]
sudo mount.davfs -o 501,502 https://your/web/site /mnt/webdav
+
then
 +
MOZ_PROGRAM=$MOZ_DEFAULT_NAME
 +
##
 +
## Try mozilla-bin
 +
##
 +
elif [ -x "$MOZ_APPRUNNER_NAME" ]
 +
then
 +
MOZ_PROGRAM=$MOZ_APPRUNNER_NAME
 +
fi
 +
fi
 +
#
 +
#
 +
##
 +
## Make sure the program is executable
 +
##
 +
if [ ! -x "$MOZ_PROGRAM" ]
 +
then
 +
moz_bail "Cannot execute $MOZ_PROGRAM."
 +
fi
 +
#
 
</pre>
 
</pre>
Mac OSX
+
 
 +
===Carry XWindows settings across sessions===
 
<pre>
 
<pre>
osascript -e ' mount volume "http://username:[email protected]:portnum" '
+
# ----------------------
or
+
# push XWindows settings
osascript -e ' mount volume "http://[email protected]:portnum" '
+
# ----------------------
or
+
[[ "$(uname)" == "SunOS" ]] && PATH=/usr/openwin/bin:$PATH
osascript -e ' try mount volume "http://webdav.address:portnum" '
+
WHOAMI=$(id | awk -F')' '{print $1}' | awk -F'(' '{print $2}')
or
+
xauth list > /tmp/xauth_list_$WHOAMI
mount -t webdav http://webdav.address:portnum /mnt/webdav  # this one won't show up in the Finder Sidebar.
+
chmod 777 /tmp/xauth_list_$WHOAMI
 +
 
 +
echo $DISPLAY > /tmp/xdisplay_$WHOAMI
 +
chmod 777 /tmp/xdisplay_$WHOAMI
 
</pre>
 
</pre>
  
===Add current hostname to list of hosts on an xcat server===
+
===Cross-platform version of whoami===
 
<pre>
 
<pre>
CMD="nodels"
+
WHOAMI=$(id | awk -F')' '{print $1}' | awk -F'(' '{print $2}')
HOST=`hostname`
 
(echo "$HOST"; $CMD) | while read server
 
do
 
    echo "server:$server"
 
done
 
</pre>
 
===What is todays 'Day Of the Year' number?===
 
<pre>
 
DOY=`perl -e 'print sub{$_[7]}->(localtime)+1;'`
 
 
</pre>
 
</pre>
  
===Convert Julian day numbers to dates===
+
===Set terminal title from command line===
<pre>
+
Put something like this in the .profile<br />
for day in 8 33 36 61 64 91 96 121 126 152 155 182 187 215 218 244 247 274 279 306 309 335 338 365; do date -d "`date +%Y`-01-01 +$(( ${day} - 1 ))days" +%d-%m-%Y; done
+
-n    do not output the trailing newline<br />
 +
-e    enable interpretation of backslash escapes<br />
 +
|0    sets title of window and icon<br />
 +
|1    sets title of icon only<br />
 +
|2    sets title of window only<br />
 +
<pre>
 +
echo -en "\033]0;`hostname`\007"
 
</pre>
 
</pre>
===Edit crontab file without crontab -e===
 
It can happen that you need to add or modify a line in the crontab of many users or across many servers at once.<br />
 
In principle, there's nothing wrong with modifying the crontab file directly. You just lose the advantages of file locking (and syntax checking) that crontab -e offers.<br />
 
Here we take a backup of the current crontab, print it out, echo an extra command and ask cron to use these as input (thus overwriting the existing crontab file). Just don't run this close to midnight :-)
 
 
<pre>
 
<pre>
crontab -l > /tmp/crontab.`date +'%Y%m%d'`
+
echo -en "\033]2;`hostname`\007"
(
 
cat /tmp/crontab.`date +'%Y%m%d'`
 
echo "02 10 * * * /home/ibmtools/scripts/oracle/export_parfile.ksh -s SID -f JDBEOP1.parfile"
 
) | crontab -
 
 
</pre>
 
</pre>
or
+
 
 +
===Remove blank lines and comments (also indented ones) from a file===
 
<pre>
 
<pre>
crontab -l > /tmp/crontab.backup
+
awk -F\: '!/^($|[:space:]*#)/ {print $2}' /etc/oratab | sort | uniq
crontab -l > /tmp/crontab.$$
 
perl -p -i -e 's!backup_send_tsm_dump!backup_export2tsm!g' /tmp/crontab.$$
 
crontab /tmp/crontab.$$
 
rm /tmp/crontab.$$
 
 
</pre>
 
</pre>
===Use shell to convert a number in scientific notation to normal===
+
or as part of a script that removes comments and blank lines from all Korn shell scripts in a directory
 
<pre>
 
<pre>
var2convert='1.2345678e3'
+
#!/usr/bin/ksh
printf -v var2convert "%.f" $var2convert
+
for i in $(ls *ksh); do
echo $var2convert  # magic!
+
    perl -p -i -e 's/^\s*#[^!]*$//; s/^\s*$//' $i
 +
done
 
</pre>
 
</pre>
===Check for jobs running longer that 24 hours===
+
 
Run from the management server across all Unix servers. Checks the 5th column in a ps listing. If it doesn't find a : (time separator), the process is running longer than 24 hours.
+
===Return elements of an array in Korn shell===
 +
From [http://unix.stackexchange.com/questions/188202/processing-output-from-an-sqlite-db-into-a-ksh-array-with-spaces here]<br />
 +
Could be used to separate the columns of an SQL select when returning to the shell<br />
 +
This approach eliminates the need to put quotes around text with spaces in it.
 
<pre>
 
<pre>
# ---------------------------------------
+
echo $KSH_VERSION
# report on long running oraibm processes
+
x="Red,Yellow is a color,Blue"
# ---------------------------------------
+
oIFS=$IFS
01 17,14 * * * rm -f /tmp/lrp.txt;/home/ibmtools/scripts/oracle/dosh -vc \"ps -ef|egrep 'oraibm|scripts/oracle'>/tmp/lrp.txt;perl -nae 'print if \$F[4] !~/:/' /tmp/lrp.txt\" >>/tmp/lrp.txt;[[ $(egrep -c 'oraibm|scripts/or
+
IFS=,
acle' /tmp/lrp.txt) -ne 0 ]] && cat /tmp/lrp.txt|mailx -s '*** long running processes - please check ***' [email protected]
+
y=($x)
 +
IFS=$oIFS
 +
echo ${y[1]}
 
</pre>
 
</pre>
  
===Global find and replace with perl (restricted to list of files provided by Unix find command)===
+
===A decent Unix Prompt===
 
<pre>
 
<pre>
find . -type f -exec perl -i -pe 's/something/else/g' {} \;
+
export PS1="`uname -n`:`whoami`[\${PWD}]# "
 +
or
 +
export PS1='($?) $'ORACLE_SID" "`whoami`"@"`uname -n`":"'$'PWD"> "
 +
export EDITOR=vi
 +
</pre>
 +
===Simple arithmetic===
 +
pipe the calculation into the shell calculator
 +
<pre>
 +
space_in_kb=$(echo $1 / 1024 | bc)
 +
</pre>
 +
Calculate the remainder (modulo) of a division calculation
 +
<pre>
 +
if [[ $(echo "${NUMBER} % 2" | bc) -eq 0 ]]; then
 +
    echo "${NUMBER} is even"
 +
else
 +
    echo "${NUMBER} is odd"
 +
fi
 
</pre>
 
</pre>
===perl function to make filenames lower case===
+
or do it in awk if scientific notation maybe involved
 
<pre>
 
<pre>
function lower {  
+
function calc { awk "BEGIN{print $*}"; }
  perl -e 'for (@ARGV) { rename $_, lc($_) unless -e lc($_); }' *
+
 
}
+
if [[ $(calc "${SPACE_USED} + ${SPACE_AVAILABLE} - ${DATABASE_SIZE") -le 0 ]]; then
 +
    echo "NOK"
 +
fi
 
</pre>
 
</pre>
  
===From the management server, search the TNS listener port for each database on a server and make an inline substitution in the ITM config files!===
+
===Script encryption and passphrase protection===
 +
Encrypt a shell script with the ability to execute the encrypted version
 +
* from [http://www.commandlinefu.com/commands/browse commandlinefu.com]
 
<pre>
 
<pre>
for i in `/home/ibmtools/scripts/oracle/dosh -c "ls -al /opt/IBM/ITM/config/*rz*cfg|grep -v lrwx"|awk '{print $NF}'`; do
+
scrypt(){ [ -n "$1" ]&&{ echo '. <(echo "$(tail -n+2 $0|base64 -d|mcrypt -dq)"); exit;'>$1.scrypt;cat $1|mcrypt|base64 >>$1.scrypt;chmod +x $1.scrypt;};}
    server=`echo $i|cut -d_ -f1 | awk -F'/' '{print $NF}'`
 
    db=`echo $i|cut -d'.' -f1 | awk -F'_' '{print $NF}'`
 
    OH=`ssh $server grep "^$db" /etc/oratab|cut -d: -f2`
 
    LISTENERPORT=`ssh $server cat $OH/network/admin/listener.ora|perl -00 -ne 'print $1 if /'$db'.*PORT.*=.*(\d{4})/s'`
 
    ssh $server perl -p -i.bak -e 's/1521/'$LISTENERPORT'/' $i
 
    ssh $server ls -al ${i}*
 
done
 
 
</pre>
 
</pre>
  
===Run a job from cron every Nth day of the month===
+
===Virtual host configuration in Apache http.conf===
Example. Execute a job every third Saturday of the month.<br />
 
Paste this into a file called calenday and put it in /usr/local/bin so it's (probably) on the PATH
 
 
<pre>
 
<pre>
#!/usr/bin/ksh
+
<VirtualHost *:80>
 
+
        ServerName dbamon
# ix is the week number of the month ("2"nd Friday of the month, "3"rd Tuesday of the month)
+
        DocumentRoot "/Volumes/data/Sites/dbamon_push"
# dy is the day number in Unix format (0 for Sunday, 1 for Monday, ... 6 for Saturday)
+
        <Directory "/Volumes/data/Sites/dbamon_push">
# eg. "calenday 3 6" returns the date of 3rd Saturday of the month.
+
                Options Includes FollowSymLinks
 
+
                AllowOverride All
ix=$1
+
                Order allow,deny
dy=$2
+
                Allow from all
SCHAR=$((($dy*2)+$dy+1))
+
        </Directory>
ECHAR=$(($SCHAR+1))
+
</VirtualHost>
cal `date '+%m %Y'` | egrep "\<[0-9]{1,2}\>" | cut -c${SCHAR}-${ECHAR} | xargs | awk {'print $'$ix'}'
 
 
 
 
</pre>
 
</pre>
Now in crontab, you should be able to do something like this:<br />
+
and in /etc/hosts, add...
 
<pre>
 
<pre>
15 20 * * * [[ `calenday 3 6` -eq `/bin/date '+%d'` ]] && su - oracle -c "run_my_backup.ksh"
+
127.0.0.1  dbamon
 
</pre>
 
</pre>
 
+
===Mount a website (or any other remote resource) locally using WebDav===
This will also work on some Unices..<br />
+
Redhat/CentOS
We send backups to a special TSM node on the second Friday of each month. This report must run a day later - but that is not guaranteed to be the second Saturday or even the 3rd. So...
 
 
<pre>
 
<pre>
30 12 8-14 * 5 sleep 86400 && su - oracle -c "/usr/bin/perl -ne 'print if /ORX_M_SOL/ .. /^STOP/' /home/oracle/incoming/dbamon_spool_tsm_*.SOL | grep Archive | grep -v Client | mailx -s 'Monthly TSM backups' orareport@xxxxxx.com"
+
yum install fuse-davfs2
 +
or
 +
yum install wdfs.x86_64
 
</pre>
 
</pre>
 
+
Debian
===ps -ef cuts off args cmd column on Solaris===
 
On AIX, ps eww <PID> shows the full argument listing of a process (NOTE: no - sign!)<br />
 
To see more than 80 characters of the last column on Solaris:
 
 
<pre>
 
<pre>
pargs <PID>
+
apt-get install davfs2
 
</pre>
 
</pre>
shows all the individual arguments to the command
+
then...
 
<pre>
 
<pre>
/usr/ucb/ps auww
+
sudo mkdir /mnt/webdav  # or whatever you'd like to call the directory
 +
sudo mount.davfs [-o option[,option]...] device mount_point
 
</pre>
 
</pre>
shows the ps listing in 'compatibility' mode (there are more compatibility commands in /usr/xpg4/bin)
+
In man's terms, that last line would translate to:
 
 
===Remove blank lines fom vi===
 
Maybe you cut and pasted a file from Windows and it's full of blank lines and Control-M's now<br />
 
There are several methods but I think this is the easiest to remember
 
 
<pre>
 
<pre>
:g/^$/d
+
id  #suppose this returns uid=501 and gid=502
 +
sudo mount.davfs -o 501,502 https://your/web/site /mnt/webdav
 
</pre>
 
</pre>
===Right pad a variable===
+
Mac OSX
a function like rpad in SQL but for Shell<br />
 
 
<pre>
 
<pre>
function rpad {
+
osascript -e ' mount volume "http://username:[email protected]:portnum" '
text=$1
+
or
padwidth=$2
+
osascript -e ' mount volume "http://[email protected]:portnum" '
padchar=$3
+
or
echo "$text" | sed -e :a -e 's/^.\{1,'$padwidth'\}$/&\'$padchar'/;ta'
+
osascript -e ' try mount volume "http://webdav.address:portnum" '
}
+
or
 +
mount -t webdav http://webdav.address:portnum /mnt/webdav  # this one won't show up in the Finder Sidebar.
 
</pre>
 
</pre>
  
===Connect to a Windows server from Linux using rdesktop===
+
===Add current hostname to list of hosts on an xcat server===
My remmina stopped working so rolled my own. Very simple really. Put this is a shell.
 
 
<pre>
 
<pre>
tsocks rdesktop -z -P -x m -a 16 -d MAIND -u sbarkley -p ****** -r disk:SOL=$HOME/Documents/SOL -g 95% 150.251.112.38 &
+
CMD="nodels"
 
+
HOST=`hostname`
where...
+
(echo "$HOST"; $CMD) | while read server
-z    - enables compression
+
do
-P    - enables bitmap caching (saves network traffic)
+
    echo "server:$server"
-x m  - disables eye-candy features
+
done
-a 16 - reduce colour pallete to 16 colours
 
-d    - domain to connect to
 
-u    - username
 
-p    - password
 
-r    - setup a shared folder
 
-g    - geometry (use W x H or percentage)
 
 
</pre>
 
</pre>
Slight problems with rdesktop not working 100% of the time. Now using xfreerdp. Seems better...
+
===What is todays 'Day Of the Year' number?===
 
<pre>
 
<pre>
xfreerdp -g 90% --ignore-certificate --gdi sw -K -d wdcrhbp05 -u oraibm -p "`cat $HOME/scripts/.oraibm.password`" -T "wdcrhbp05_oraibm" --plugin cliprdr --plugin rdpdr --data disk:SOL:/home/bey9at77/Documents/SOL -- --plugin rdpsnd --data alsa -- 150.251.112.25 &
+
DOY=`perl -e 'print sub{$_[7]}->(localtime)+1;'`
 
</pre>
 
</pre>
  
===Reset your password bypassing password rules===
+
===Convert Julian day numbers to dates===
must be done as root
 
 
<pre>
 
<pre>
echo "user:new_password" | chpasswd
+
for day in 8 33 36 61 64 91 96 121 126 152 155 182 187 215 218 244 247 274 279 306 309 335 338 365; do date -d "`date +%Y`-01-01 +$(( ${day} - 1 ))days" +%d-%m-%Y; done
 
</pre>
 
</pre>
===Sum the sizes of all files of an ls listing===
+
===Send crontab job output to a date formatted log file===
It'll check to see if the sum of filesizes corresponds with the df -g (or h) listing (can get messed up due to open but deleted files)
+
This will run a job every 5 minutes and send the output to a file ending with a time in hours and minutes.<br />
 +
The thing to note is the escaped percent signs. This is because a % sign is interpreted by cron to mean a newline character. Everything after the first % is treated as input to the program.
 
<pre>
 
<pre>
cd /oracle/export
+
*/5 *  * * * /var/www/cgi-bin/dbamon_collector.ksh      >/tmp/dbamon_collector.log.$(date "+\%H\%M") 2>&1
df -g .
 
find . -name "*dmp*" -ls |  awk '{ SUM += $7} END { print SUM/1024/1024/1024 }'
 
 
</pre>
 
</pre>
 
+
===Edit crontab file without crontab -e===
===Mount an iso image under Linux===
+
It can happen that you need to add or modify a line in the crontab of many users or across many servers at once.<br />
 +
In principle, there's nothing wrong with modifying the crontab file directly. You just lose the advantages of file locking (and syntax checking) that crontab -e offers.<br />
 +
Here we take a backup of the current crontab, print it out, echo an extra command and ask cron to use these as input (thus overwriting the existing crontab file). Just don't run this close to midnight :-)
 
<pre>
 
<pre>
mkdir -p /mnt/cdrom
+
crontab -l > /tmp/crontab.`date '+%Y%m%d'`
mount -o loop /dev/cdrom /mnt/cdrom
+
(
 +
cat /tmp/crontab.`date +'%Y%m%d'`
 +
echo "02 10 * * * /home/ibmtools/scripts/oracle/export_parfile.ksh -s SID -f JDBEOP1.parfile"
 +
) | crontab -
 
</pre>
 
</pre>
===How many processors on the machine?===
+
or
* AIX
 
 
<pre>
 
<pre>
lsdev -C|grep Process|wc -l
+
crontab -l > /tmp/crontab.backup
</pre>
+
crontab -l > /tmp/crontab.$$
* Solaris
+
perl -p -i -e 's!backup_send_tsm_dump!backup_export2tsm!g' /tmp/crontab.$$
<pre>
+
crontab /tmp/crontab.$$
psrinfo -v|grep "Status of processor"|wc -l
+
rm /tmp/crontab.$$
 
</pre>
 
</pre>
* Linux
+
or
 
<pre>
 
<pre>
cat /proc/cpuinfo|grep processor|wc -l
+
crontab -l >$HOME/crontab.$(date '+%Y%m%d')
 +
crontab -l | perl -p -e 's|/nas/software/oracle/scripts|/oracle/scripts|' | crontab
 
</pre>
 
</pre>
  
===Quick, simple, understandable example of how to use RRDTool===
+
===Use shell to convert a number in scientific notation to normal===
* [[RRDTool]]
 
 
 
===Use expect to respond automatically to interactive programs===
 
 
<pre>
 
<pre>
#!/usr/bin/expect -f
+
var2convert='1.2345678e3'
spawn /usr/tivoli/tsm/client/oracle/bin64/tdpoconf passw -tdpo_optfile=/oracle/[lindex $argv 0]/admin/tdpo.opt
+
printf -v var2convert "%.f" $var2convert
expect "assword:" {send "password\r"}
+
echo $var2convert  # magic!
expect "assword:" {send "password\r"}
 
expect "assword:" {send "password\r"}
 
 
</pre>
 
</pre>
===Within a shell script set up simultaneous output to both terminal and a file using a FIFO (named pipes)===
+
===Check for jobs running longer that 24 hours===
examples [http://www.unix.com/shell-programming-and-scripting/85584-redirect-within-ksh.html here on unix.com]
+
Run from the management server across all Unix servers. Checks the 5th column in a ps listing. If it doesn't find a : (time separator), the process is running longer than 24 hours.
* general info on redirections [http://www.catonmat.net/blog/bash-one-liners-explained-part-three/ here at catonmat.net]
 
 
<pre>
 
<pre>
#!/bin/ksh
+
# ---------------------------------------
 +
# report on long running oraibm processes
 +
# ---------------------------------------
 +
01 17,14 * * * rm -f /tmp/lrp.txt;/home/ibmtools/scripts/oracle/dosh -vc \"ps -ef|egrep 'oraibm|scripts/oracle'>/tmp/lrp.txt;perl -nae 'print if \$F[4] !~/:/' /tmp/lrp.txt\" >>/tmp/lrp.txt;[[ $(egrep -c 'oraibm|scripts/or
 +
acle' /tmp/lrp.txt) -ne 0 ]] && cat /tmp/lrp.txt|mailx -s '*** long running processes - please check ***' [email protected]
 +
</pre>
  
REDIR=test.redir
+
===Global find and replace with perl (restricted to list of files provided by Unix find command)===
FIFO=test.pipe
+
<pre>
[[ -e $FIFO ]] || mkfifo $FIFO
+
find . -type f -exec perl -i -pe 's/something/else/g' {} \;
 +
</pre>
 +
===perl function to make filenames lower case===
 +
<pre>
 +
function lower {
 +
  perl -e 'for (@ARGV) { rename $_, lc($_) unless -e lc($_); }' *
 +
}
 +
</pre>
  
# make a new channel(3) and copy channel 1's destination as its own (does NOT POINT TO channel 1's destination)
+
===From the management server, search the TNS listener port for each database on a server and make an inline substitution in the ITM config files!===
# this allows the normal output to continue to STDOUT but also get printed to whatever file is attached to channel 3
+
<pre>
exec 3>&1
+
for i in `/home/ibmtools/scripts/oracle/dosh -c "ls -al /opt/IBM/ITM/config/*rz*cfg|grep -v lrwx"|awk '{print $NF}'`; do
 +
    server=`echo $i|cut -d_ -f1 | awk -F'/' '{print $NF}'`
 +
    db=`echo $i|cut -d'.' -f1 | awk -F'_' '{print $NF}'`
 +
    OH=`ssh $server grep "^$db" /etc/oratab|cut -d: -f2`
 +
    LISTENERPORT=`ssh $server cat $OH/network/admin/listener.ora|perl -00 -ne 'print $1 if /'$db'.*PORT.*=.*(\d{4})/s'`
 +
    ssh $server perl -p -i.bak -e 's/1521/'$LISTENERPORT'/' $i
 +
    ssh $server ls -al ${i}*
 +
done
 +
</pre>
  
# anything coming in on the pipe, send it to $REDIR and to channel 3
+
===Run a job from cron every Nth day of the month===
tee $REDIR <$FIFO >&3 &
+
Example. Execute a job every third Saturday of the month.<br />
 +
Paste this into a file called calenday and put it in /usr/local/bin so it's (probably) on the PATH
 +
<pre>
 +
#!/usr/bin/ksh
  
# redirect STDOUT to the pipe
+
# ix is the week number of the month ("2"nd Friday of the month, "3"rd Tuesday of the month)
exec > $FIFO
+
# dy is the day number in Unix format (0 for Sunday, 1 for Monday, ... 6 for Saturday)
 +
# eg. "calenday 3 6" returns the date of 3rd Saturday of the month.
  
echo "going to default output"
+
ix=$1
echo "forcing to channel 1" >&1
+
dy=$2
echo "forcing to channel 2" >&2
+
SCHAR=$((($dy*2)+$dy+1))
echo "forcing to channel 3" >&3
+
ECHAR=$(($SCHAR+1))
</pre>
+
cal `date '+%m %Y'` | egrep "\<[0-9]{1,2}\>" | cut -c${SCHAR}-${ECHAR} | xargs | awk {'print $'$ix'}'
====More elaborate example====
+
 
found [http://stackoverflow.com/questions/2288939/create-a-pipe-that-writes-to-multiple-files-tee here on stackoverflow]
+
</pre>
 +
Now in crontab, you should be able to do something like this:<br />
 +
<pre>
 +
15 20 * * * [[ `calenday 3 6` -eq `/bin/date '+%d'` ]] && su - oracle -c "run_my_backup.ksh"
 +
</pre>
 +
 
 +
This will also work on some Unices..<br />
 +
We send backups to a special TSM node on the second Friday of each month. This report must run a day later - but that is not guaranteed to be the second Saturday or even the 3rd. So...
 
<pre>
 
<pre>
#!/bin/sh
+
30 12 8-14 * 5 sleep 86400 && su - oracle -c "/usr/bin/perl -ne 'print if /ORX_M_SOL/ .. /^STOP/' /home/oracle/incoming/dbamon_spool_tsm_*.SOL | grep Archive | grep -v Client | mailx -s 'Monthly TSM backups' [email protected]"
 +
</pre>
  
# Author: Harvey Chapman <hchapman _AT_ 3gfp.com>
+
===ps listing does not show start time after 24 hours===
# Description: POSIX shell functions that can be used with tee to simultaneously put
+
But you can see elapsed time using your own ps command
#              stderr and stdout to both a file and stdout
+
<pre>
#
+
/usr/bin/ps -eo etime,user,pid,ppid,cpu,start,tty,time,args|tail -n +2|sort
# Based on:
+
</pre>
#    Re: How to redirect stderr and stdout to a file plus display at the same time
 
#    http://www.travishartwell.net/blog/2006/08/19_2220
 
  
#
+
===ps -ef cuts off args cmd column on Solaris===
# Original example function from Travis Hartwell's blog.
+
====To see more than 80 characters of the last column on Solaris====
# Note: I've made minor changes to it.
+
This shows all the individual arguments to the command
example()
+
<pre>
{
+
pargs <pid>
  OUTPUT_LOG=output.log
+
</pre>
  OUTPUT_PIPE=output.pipe
+
This shows the ps listing in 'compatibility' mode (there are more compatibility commands in /usr/xpg4/bin)
 +
<pre>
 +
/usr/ucb/ps auww
 +
</pre>
 +
====To see more than 80 characters of the last column on AIX====
 +
This shows the full argument listing of a process (NOTE: no minus sign!)
 +
<pre>
 +
ps eww <pid>
 +
</pre>
  
  # This should really be -p to test that it's a pipe.
+
===Remove blank / empty lines from vi ===
  if [ ! -e $OUTPUT_PIPE ]; then
+
Maybe you cut and pasted a file from Windows and it's full of blank lines and Control-M's now<br />
      mkfifo $OUTPUT_PIPE
+
There are several methods but I think this is the easiest to remember
  fi
+
<pre>
 +
:g/^$/d
 +
</pre>
  
  # This should really be -f to test that it's a regular file.
+
===Right pad a variable===
  if [ -e $OUTPUT_LOG ]; then
+
a function like rpad in SQL but for Shell<br />
      rm $OUTPUT_LOG
+
<pre>
  fi
+
function rpad {
 +
text=$1
 +
padwidth=$2
 +
padchar=$3
 +
echo "$text" | sed -e :a -e 's/^.\{1,'$padwidth'\}$/&\'$padchar'/;ta'
 +
}
 +
</pre>
  
  exec 3>&1 4>&2
+
===Connect to a Windows server from Linux using rdesktop===
  tee $OUTPUT_LOG < $OUTPUT_PIPE >&3 &
+
My remmina stopped working so rolled my own. Very simple really. Put this is a shell.
  tpid=$!
+
<pre>
  exec > $OUTPUT_PIPE 2>&1
+
tsocks rdesktop -z -P -x m -a 16 -d MAIND -u sbarkley -p ****** -r disk:SOL=$HOME/Documents/SOL -g 95% 150.251.112.38 &
  
  echo "This is on standard out"
+
where...
  echo "This is on standard err" >&2
+
-z    - enables compression
 
+
-P    - enables bitmap caching (saves network traffic)
  exec 1>&3 3>&- 2>&4 4>&-
+
-x m  - disables eye-candy features
  wait $tpid
+
-a 16 - reduce colour pallete to 16 colours
 
+
-d    - domain to connect to
  rm $OUTPUT_PIPE
+
-u    - username
}
+
-p    - password
 +
-r    - setup a shared folder
 +
-g    - geometry (use W x H or percentage)
 +
</pre>
 +
Slight problems with rdesktop not working 100% of the time. Now using xfreerdp. Seems better...
 +
<pre>
 +
xfreerdp -g 90% --ignore-certificate --gdi sw -K -d wdcrhbp05 -u oraibm -p "`cat $HOME/scripts/.oraibm.password`" -T "wdcrhbp05_oraibm" --plugin cliprdr --plugin rdpdr --data disk:SOL:/home/bey9at77/Documents/SOL -- --plugin rdpsnd --data alsa -- 150.251.112.25 &
 +
</pre>
  
# A slightly reduced version of example()
+
===Reset your password bypassing password rules===
example2()
+
must be done as root
{
+
<pre>
  OUTPUT_LOG=output.log
+
echo "user:new_password" | chpasswd
  OUTPUT_PIPE=output.pipe
+
</pre>
 
+
===Sum the sizes of all files of an ls listing===
  rm -f $OUTPUT_PIPE
+
It'll check to see if the sum of filesizes corresponds with the df -g (or h) listing (can get messed up due to open but deleted files)
  mkfifo $OUTPUT_PIPE
+
<pre>
  rm -f $OUTPUT_LOG
+
cd /oracle/export
 +
df -g .
 +
find . -name "*dmp*" -ls |  awk '{ SUM += $7} END { print SUM/1024/1024/1024 }'
 +
</pre>
  
  tee $OUTPUT_LOG < $OUTPUT_PIPE &
+
===Mount an iso image under Linux===
  tpid=$!
+
<pre>
 +
mkdir -p /mnt/cdrom
 +
mount -o loop /dev/cdrom /mnt/cdrom
 +
</pre>
 +
===How many processors on the machine?===
 +
* AIX
 +
<pre>
 +
lsdev -C|grep Process|wc -l
 +
</pre>
 +
* Solaris
 +
<pre>
 +
psrinfo -v|grep "Status of processor"|wc -l
 +
</pre>
 +
* Linux
 +
<pre>
 +
cat /proc/cpuinfo|grep processor|wc -l
 +
</pre>
  
  exec 3>&1 4>&2 >$OUTPUT_PIPE 2>&1
+
===Quick, simple, understandable example of how to use RRDTool===
 +
* [[RRDTool]]
  
  echo "This is on standard out"
+
===Use expect to respond automatically to interactive programs===
  echo "This is on standard err" >&2
+
<pre>
 
+
#!/usr/bin/expect -f
  exec 1>&3 3>&- 2>&4 4>&-
+
spawn /usr/tivoli/tsm/client/oracle/bin64/tdpoconf passw -tdpo_optfile=/oracle/[lindex $argv 0]/admin/tdpo.opt
  wait $tpid
+
expect "assword:" {send "password\r"}
  rm -f $OUTPUT_PIPE
+
expect "assword:" {send "password\r"}
 +
expect "assword:" {send "password\r"}
 +
</pre>
 +
===Use expect to allow file copy with scp (if ssh keys are not an option)===
 +
<pre>
 +
#!/usr/bin/expect -f
 +
spawn scp /home/oracle/.profile oracle@hn512:/tmp/prfl
 +
set pass "thepassword"
 +
expect {
 +
        password: {send "$pass\r" ; exp_continue}
 +
        eof exit
 
}
 
}
 +
</pre>
  
#
+
===Within a shell script set up simultaneous output to both terminal and a file using a FIFO (named pipes)===
# Logging methods based on above. See the example below for how to use them.
+
or "How to send shell output to screen/stdout as well as to a logfile using tee and redirection with exec"<br />
#
+
<br />
 +
examples [http://www.unix.com/shell-programming-and-scripting/85584-redirect-within-ksh.html here on unix.com]
 +
* general info on redirections [http://www.catonmat.net/blog/bash-one-liners-explained-part-three/ here at catonmat.net]
 +
<pre>
 +
#!/bin/ksh
  
# Usage: start_logging [delete_existing_logfile]
+
REDIR=test.redir
start_logging()
+
FIFO=test.pipe
{
+
[[ -e $FIFO ]] || mkfifo $FIFO
  # Check to see if OUTPUT_LOG and OUTPUT_PIPE need to be defined.
+
 
  if [ -z "$OUTPUT_LOG" ]; then
+
# make a new channel(3) and copy channel 1's destination as its own (does NOT POINT TO channel 1's destination)
    OUTPUT_LOG=output.log
+
# this allows the normal output to continue to STDOUT but also get printed to whatever file is attached to channel 3
  fi
+
exec 3>&1
  if [ -z "$OUTPUT_PIPE" ]; then
 
    OUTPUT_PIPE=output.pipe
 
  fi
 
  # Make sure that we're not already logging.
 
  if [ -n "$OUTPUT_PID" ]; then
 
    echo "Logging already started!"
 
    return 1
 
  fi
 
  
  # Always remove the log and pipe first.
+
# anything coming in on the pipe, send it to $REDIR and to channel 3
  rm -f $OUTPUT_PIPE
+
tee $REDIR <$FIFO >&3 &
  # Delete the logfile first if told to.
 
  if [ "$1" = delete_existing_logfile ]; then
 
    rm -f $OUTPUT_LOG
 
  fi
 
  
  mkfifo $OUTPUT_PIPE
+
# redirect STDOUT to the pipe
  tee -a $OUTPUT_LOG < $OUTPUT_PIPE &
+
exec > $FIFO
  OUTPUT_PID=$!
 
  
  exec 3>&1 4>&2 >$OUTPUT_PIPE 2>&1
+
echo "going to default output"
}
+
echo "forcing to channel 1" >&1
 +
echo "forcing to channel 2" >&2
 +
echo "forcing to channel 3" >&3
 +
</pre>
 +
====More elaborate example====
 +
found [http://stackoverflow.com/questions/2288939/create-a-pipe-that-writes-to-multiple-files-tee here on stackoverflow]
 +
<pre>
 +
#!/bin/sh
  
stop_logging()
+
# Author: Harvey Chapman <hchapman _AT_ 3gfp.com>
{
+
# Description: POSIX shell functions that can be used with tee to simultaneously put
  # Make sure that we're currently logging.
+
#              stderr and stdout to both a file and stdout
  if [ -z "$OUTPUT_PID" ]; then
+
#
    echo "Logging not yet started!"
+
# Based on:
    return 1
+
#    Re: How to redirect stderr and stdout to a file plus display at the same time
  fi
+
#    http://www.travishartwell.net/blog/2006/08/19_2220
  exec 1>&3 3>&- 2>&4 4>&-
 
  wait $OUTPUT_PID
 
  rm -f $OUTPUT_PIPE
 
  unset OUTPUT_PID
 
}
 
  
example3()
+
#
 +
# Original example function from Travis Hartwell's blog.
 +
# Note: I've made minor changes to it.
 +
example()
 
{
 
{
   start_logging
+
   OUTPUT_LOG=output.log
   #start_logging delete_existing_logfile
+
   OUTPUT_PIPE=output.pipe
  echo "This is on standard out"
 
  echo "This is on standard err" >&2
 
  stop_logging
 
}
 
</pre>
 
  
===RedHat root filesystem has gone read-only===
+
  # This should really be -p to test that it's a pipe.
* [http://www.unixarena.com/2013/09/redhat-linux-how-to-fix-read-only-root.html How to fix read only root file system]
+
  if [ ! -e $OUTPUT_PIPE ]; then
 +
      mkfifo $OUTPUT_PIPE
 +
  fi
  
===Kill all processes for a user===
+
  # This should really be -f to test that it's a regular file.
<pre>
+
  if [ -e $OUTPUT_LOG ]; then
for prc in `ps -ef | grep -E "^ +[o]racle" | awk '{print $2}'`; do
+
      rm $OUTPUT_LOG
    kill $prc
+
  fi
done
 
</pre>
 
  
===isRGHere===
+
  exec 3>&1 4>&2
Checks if resource group is on this leg of an HACMP cluster. Returns 0 if true else 1.
+
  tee $OUTPUT_LOG < $OUTPUT_PIPE >&3 &
<pre>
+
  tpid=$!
#!/usr/bin/ksh
+
  exec > $OUTPUT_PIPE 2>&1
  
SCRIPT=`basename $0`
+
  echo "This is on standard out"
 +
  echo "This is on standard err" >&2
  
function rctest
+
  exec 1>&3 3>&- 2>&4 4>&-
{
+
  wait $tpid
exitcode=$1
 
msg=$2
 
if [ $exitcode -ne 0 ]; then
 
        echo "********************************************************************************"
 
        echo "\nScript $SCRIPT finished with errors."
 
        echo "$msg."
 
        echo "Returncode : $exitcode."
 
        echo "\n********************************************************************************"
 
  
        fi
+
  rm $OUTPUT_PIPE
exit $exitcode
+
}
  
}
+
# A slightly reduced version of example()
 +
example2()
 +
{
 +
  OUTPUT_LOG=output.log
 +
  OUTPUT_PIPE=output.pipe
  
RGINFO=/usr/es/sbin/cluster/utilities/clRGinfo
+
  rm -f $OUTPUT_PIPE
[[ ! -f $RGINFO ]] &&  rctest 1 "clRGinfo not found"
+
  mkfifo $OUTPUT_PIPE
 +
  rm -f $OUTPUT_LOG
  
if [ $# -eq 1 ]
+
  tee $OUTPUT_LOG < $OUTPUT_PIPE &
then
+
  tpid=$!
        RG=`echo $1 | cut -c 1-14`
+
 
else
+
  exec 3>&1 4>&2 >$OUTPUT_PIPE 2>&1
        rctest 10  "Usage: `basename $0` <RG name>"
+
 
fi
+
  echo "This is on standard out"
 +
  echo "This is on standard err" >&2
  
$RGINFO |grep -qwp $RG ||  rctest 9 "$RG is not defined"
+
  exec 1>&3 3>&- 2>&4 4>&-
 +
  wait $tpid
 +
  rm -f $OUTPUT_PIPE
 +
}
  
THISNODE=`/usr/es/sbin/cluster/utilities/get_local_nodename | cut -c 1-14`
+
#
$RGINFO |grep -wp $RG |grep -w $THISNODE |grep -wq ONLINE
+
# Logging methods based on above. See the example below for how to use them.
</pre>
+
#
===AIX: add a user to a group===
 
<pre>
 
chgrpmem -m + oracle ibmtls
 
</pre>
 
===grep -p (for paragraph) works on AIX but not on Linux or Solaris===
 
Use awk instead
 
<pre>
 
awk 'BEGIN {FS="\n" RS="\n\n"} /search pattern/ { do something }' <file>
 
/usr/xpg4/bin/awk 'BEGIN {RS="\n\n";FS="\n"} /AGRHDWQ1/ {print $2}' dsm.sys | awk '{print $NF}'
 
</pre>
 
this prints the last word of the second ''line'' in the paragraph in dsm.sys that contains the search term AGRHDWQ1.<br />
 
Or slightly simpler...
 
<pre>
 
awk -v RS='' '/NHAPPLP1/' /etc/tsm/dsm.sys    # (use /usr/xpg4/bin/awk on Solaris)
 
</pre>
 
or, case insensitively:
 
<pre>
 
awk -v RS='' 'tolower($0) ~/so_u_clubqa_orx_d_cab/' /etc/tsm/dsm.sys
 
</pre>
 
Using -v means you don't have to use a BEGIN section.
 
  
===debug/redirect log of a shell===
+
# Usage: start_logging [delete_existing_logfile]
<pre>
+
start_logging()
#!/usr/bin/ksh
+
{
exec 2>/tmp/mytest
+
  # Check to see if OUTPUT_LOG and OUTPUT_PIPE need to be defined.
</pre>
+
  if [ -z "$OUTPUT_LOG" ]; then
===Different ways of Iteration in korn shell with a while loop===
+
    OUTPUT_LOG=output.log
<pre>
+
  fi
IFS="|"
+
  if [ -z "$OUTPUT_PIPE" ]; then
exec 0<$statfile
+
     OUTPUT_PIPE=output.pipe
while read host db started stopped
+
  fi
do
+
  # Make sure that we're not already logging.
    rrdfile="export_duration_${host}_${db}.rrd"
+
  if [ -n "$OUTPUT_PID" ]; then
     $RRDTOOL update ${RRDDIR}/${rrdfile} $started:$started $stopped
+
     echo "Logging already started!"
done
+
    return 1
</pre>
+
  fi
or
+
 
<pre>
+
  # Always remove the log and pipe first.
while read host db started stopped
+
  rm -f $OUTPUT_PIPE
do
+
  # Delete the logfile first if told to.
    rrdfile="export_duration_${host}_${db}.rrd"
+
  if [ "$1" = delete_existing_logfile ]; then
     $RRDTOOL update ${RRDDIR}/${rrdfile} $started:$started $stopped
+
    rm -f $OUTPUT_LOG
done <statfile
+
  fi
</pre>
+
 
or
+
  mkfifo $OUTPUT_PIPE
<pre>
+
  tee -a $OUTPUT_LOG < $OUTPUT_PIPE &
    cat $statfile | sort -nk4 | while IFS=\| read host db type started stopped
+
  OUTPUT_PID=$!
    do
 
        [[ "$stopped" == "" ]] && continue
 
        rrdfile="export_duration_${host}_${db}.rrd"
 
        $RRDTOOL update ${RRDDIR}/${rrdfile} ${started}:${started}:${stopped}
 
        [[ $? -ne 0 ]] && echo "nok: $?"
 
    done
 
</pre>
 
  
===Filesystem 100% full, what's taking up all the space?===
+
  exec 3>&1 4>&2 >$OUTPUT_PIPE 2>&1
<pre>
+
}
find /oracle/endur -xdev -ls|sort -nr +6|head
 
</pre>
 
or
 
<pre>
 
/dev/esb01fs010001      1.00      0.00  100%    1838    69% /oracle
 
beuxdsysesb01:root[/root]# cd /oracle
 
beuxdsysesb01:root[/oracle]# du -gsx * | sort -n
 
0.00    checkpoints
 
0.00    flash_recovery_area
 
0.00    lost+found
 
0.00    oraInst.loc
 
0.00    oraInventory
 
0.09    admin
 
0.99    diag
 
</pre>
 
cd  diag and repeat until culprits are found
 
  
===Show paged memory hogs on AIX===
+
stop_logging()
<pre>
+
{
svmon -Pt20 | perl -e 'while(<>){print if($.==2||$&&&!$s++);$.=0 if(/^-+$/)}'
+
  # Make sure that we're currently logging.
</pre>
+
  if [ -z "$OUTPUT_PID" ]; then
 
+
    echo "Logging not yet started!"
===Remove a directory/file containing weird control characters===
+
    return 1
Use ls with -i to see inode listing
+
  fi
<pre>
+
  exec 1>&3 3>&- 2>&4 4>&-
ls -bali
+
  wait $OUTPUT_PID
 +
  rm -f $OUTPUT_PIPE
 +
  unset OUTPUT_PID
 +
}
 +
 
 +
example3()
 +
{
 +
  start_logging
 +
  #start_logging delete_existing_logfile
 +
  echo "This is on standard out"
 +
  echo "This is on standard err" >&2
 +
  stop_logging
 +
}
 
</pre>
 
</pre>
Use find with -inum to get the filename and -exec to remove it
+
 
 +
===RedHat root filesystem has gone read-only===
 +
* [http://www.unixarena.com/2013/09/redhat-linux-how-to-fix-read-only-root.html How to fix read only root file system]
 +
 
 +
===Kill all processes for a user===
 
<pre>
 
<pre>
find . -inum <inode from ls listing> -exec rm -f {} \;
+
for prc in `ps -ef | grep -E "^ +[o]racle" | awk '{print $2}'`; do
 +
    kill $prc
 +
done
 
</pre>
 
</pre>
  
===Run a local script on a remote host===
+
===isRGHere===
 +
Checks if resource group is on this leg of an HACMP cluster. Returns 0 if true else 1.
 
<pre>
 
<pre>
ssh user@host 'sh' < your_script.sh
+
#!/usr/bin/ksh
</pre>
 
First of all, this command is a redirection: your shell will open the file your_script.sh and feed it as input to the ssh command. ssh, in turn, will tunnel its stdin to the remote command, namely, sh instance. And sh without arguments reads its script from stdin. So we got sh instance, which is launched on remote host, but reads commands from your local file.
 
  
===Return a list of Oracle databases running on a list of remote servers===
+
SCRIPT=`basename $0`
<pre>
 
#!/bin/ksh
 
  
serverlist=`cat /home/tools/ini/system/oracle_servers | sort -n | tr "\n" " "`
+
function rctest
 +
{
 +
exitcode=$1
 +
msg=$2
 +
if [ $exitcode -ne 0 ]; then
 +
        echo "********************************************************************************"
 +
        echo "\nScript $SCRIPT finished with errors."
 +
        echo "$msg."
 +
        echo "Returncode : $exitcode."
 +
        echo "\n********************************************************************************"
  
if [ -z "${serverlist}" ]
+
        fi
then
+
exit $exitcode
    echo "no servers found" && exit 1
 
fi
 
  
 +
}
 +
 +
RGINFO=/usr/es/sbin/cluster/utilities/clRGinfo
 +
[[ ! -f $RGINFO ]] &&  rctest 1 "clRGinfo not found"
 +
 +
if [ $# -eq 1 ]
 +
then
 +
        RG=`echo $1 | cut -c 1-14`
 +
else
 +
        rctest 10  "Usage: `basename $0` <RG name>"
 +
fi
  
for server in ${serverlist}
+
$RGINFO |grep -qwp $RG || rctest 9 "$RG is not defined"
do
 
    ssh ${server} "ps -ef | grep [o]ra_pmon_" >/tmp/${server}.dblist
 
done
 
  
for server in ${serverlist}
+
THISNODE=`/usr/es/sbin/cluster/utilities/get_local_nodename | cut -c 1-14`
do
+
$RGINFO |grep -wp $RG |grep -w $THISNODE |grep -wq ONLINE
    cat /tmp/${server}.dblist | awk -F_ -v SRV=${server} 'BEGIN {print SRV ":"} {print $NF}' | tr "\n" " "
 
    echo
 
done
 
 
</pre>
 
</pre>
===Clever trick to check whether SQL output needs sending to someone===
+
===AIX: add a user to a group===
 
<pre>
 
<pre>
#!/bin/bash
+
chgrpmem -m + oracle ibmtls
tempfile=/tmp/audit_locked_accounts_$ORACLE_SID.txt
+
</pre>
 +
===Find swear words in scripts by comparing it to a list found on the internet===
 +
<pre>
 +
wget "http://www.bannedwordlist.com/lists/swearWords.csv" -O /tmp/s ; for word in $(cat /tmp/s | sed -e 's/ /_/g' -e 's/,/ /g') ; do grep -wR $word *; done | less
 +
</pre>
  
# Start sqlplus and check for locked accounts
+
===grep -p (for paragraph) works on AIX but not on Linux or Solaris===
sqlplus -S "/ as sysdba" << EOF > $tempfile
+
Use awk instead
set pages 0
+
<pre>
select 'The following accounts were found to be unlocked and should not be'
+
awk 'BEGIN {FS="\n" RS="\n\n"} /search pattern/ { do something }' <file>
from dual;
+
/usr/xpg4/bin/awk 'BEGIN {RS="\n\n";FS="\n"} /AGRHDWQ1/ {print $2}' dsm.sys | awk '{print $NF}'
 +
</pre>
 +
this prints the last word of the second ''line'' in the paragraph in dsm.sys that contains the search term AGRHDWQ1.<br />
 +
Or slightly simpler...
 +
<pre>
 +
awk -v RS='' '/NHAPPLP1/' /etc/tsm/dsm.sys    # (use /usr/xpg4/bin/awk on Solaris)
 +
</pre>
 +
or, case insensitively:
 +
<pre>
 +
awk -v RS='' 'tolower($0) ~/so_u_clubqa_orx_d_cab/' /etc/tsm/dsm.sys
 +
</pre>
 +
Using -v means you don't have to use a BEGIN section.
  
def exit_status = 0
+
===debug/redirect log of a shell===
col xs new_value exit_status
 
 
 
select username
 
,      account_status
 
,      1 as xs
 
from  dba_users
 
where  account_status != 'LOCKED'
 
and    username in ('HR', 'SCOTT', 'OUTLN', 'MDSYS', 'CTXSYS')
 
/
 
exit &exit_status
 
EOF
 
 
 
# If the exit status of sqlplus was not 0 then we will send an email
 
if [ $? != 0 ]; then
 
    mail -s "Accounts Unlocked in $ORACLE_SID" oracle < $tempfile
 
fi
 
</pre>
 
 
 
===Check RMAN logfiles for errors from cron every day===
 
 
<pre>
 
<pre>
00 09 * * * /home/tools/scripts/oracle/dosh 'find /home/tools/logs/rman -name "*online.log" -mtime -1 -exec sed -ne "/^RMAN-/,/^$/p" {} \\; -ls' | mailx
+
#!/usr/bin/ksh
-s 'RMAN errors last night' [email protected]
+
exec 2>/tmp/mytest
 
</pre>
 
</pre>
 +
===Different ways of Iteration in korn shell with a while loop===
 
<pre>
 
<pre>
/home/ibmtools/scripts/oracle/dosh 'find /oracle/export -name "expdp*log" -mtime -1 -exec grep ORA- {} \; -ls' | mailx -s 'Datapump errors for Baxter last night' [email protected]
+
IFS="|"
 +
exec 0<$statfile
 +
while read host db started stopped
 +
do
 +
    rrdfile="export_duration_${host}_${db}.rrd"
 +
    $RRDTOOL update ${RRDDIR}/${rrdfile} $started:$started $stopped
 +
done
 +
</pre>
 +
or
 +
<pre>
 +
while read host db started stopped
 +
do
 +
    rrdfile="export_duration_${host}_${db}.rrd"
 +
    $RRDTOOL update ${RRDDIR}/${rrdfile} $started:$started $stopped
 +
done <statfile
 
</pre>
 
</pre>
===Run a script on multiple servers===
+
or
 
<pre>
 
<pre>
#!/bin/ksh
+
    cat $statfile | sort -nk4 | while IFS=\| read host db type started stopped
# ==============================================================================
+
    do
# Name         : dosh  (Distributed Oracle SHell)
+
        [[ "$stopped" == "" ]] && continue
# Description  : Runs a command on all Oracle servers
+
        rrdfile="export_duration_${host}_${db}.rrd"
#
+
         $RRDTOOL update ${RRDDIR}/${rrdfile} ${started}:${started}:${stopped}
# Parameters  : h - displays help
+
        [[ $? -ne 0 ]] && echo "nok: $?"
#                v - verbose (default, like all unix commands is silent)
+
    done
#                c - command to be executed
+
</pre>
#
 
# Example      : ./dosh -v -c 'ls -al'
 
#
 
# Modification History
 
# ====================
 
# When      Who              What
 
# ========= ================= ==================================================
 
# 08-FEB-13 Stuart Barkley    Created
 
# ==============================================================================
 
  
# --------------------------------------------------------------------------
+
===Filesystem 100% full, what's taking up all the space?===
# this list of servers is generated by the DBAMON tool so will be up to date
+
<pre>
# --------------------------------------------------------------------------
+
find /oracle/endur -xdev -ls|sort -nr +6|head
serverfile=/home/ibmtools/etc/oracle/oracle_servers
+
</pre>
[[ -z "${serverfile}" ]] && echo "Server list ${serverfile} not found" && exit 1
+
or
 
+
<pre>
serverlist=`cat ${serverfile} | sort -n | tr "\n" " "`
+
/dev/esb01fs010001      1.00      0.00  100%    1838    69% /oracle
 +
beuxdsysesb01:root[/root]# cd /oracle
 +
beuxdsysesb01:root[/oracle]# du -gsx * | sort -n
 +
0.00    checkpoints
 +
0.00    flash_recovery_area
 +
0.00    lost+found
 +
0.00    oraInst.loc
 +
0.00    oraInventory
 +
0.09    admin
 +
0.99    diag
 +
</pre>
 +
cd  diag and repeat until culprits are found
  
 +
===Show paged memory hogs on AIX===
 +
<pre>
 +
svmon -Pt20 | perl -e 'while(<>){print if($.==2||$&&&!$s++);$.=0 if(/^-+$/)}'
 +
</pre>
  
# -------------------------
+
===Capitalise the first letter of a word in Korn Shell===
# get the arguments, if any
+
Not as easy as it sounds if it needs to work in non-ksh93 shells
# -------------------------
+
<pre>
while getopts "hvc:" OPT
+
function capit {
do
+
    typeset -u first
     case "$OPT" in
+
     first=${1%"${1#?}"}
     h) echo "\nUsage: $0 [-v] [-h] -c '<command_to_be_executed_remotely>'\n";
+
     printf "%s\n" "${first}${1#?}"
      exit;
+
    return 0
      ;;
+
}
    v) VERBOSE="Y";
+
</pre>
      ;;
+
or maybe more neatly done in Perl...<br />
     c) CMMND=$OPTARG;
+
This will capitalise each word in a sentence passed into it
      ;;
+
<pre>
    *) echo "\nUsage: $0 [-v] [-h] -c '<command_to_be_executed_remotely>'\n";
+
function capit {
      exit;
+
     echo "$1" |  perl -pe "s/([\w']+)/\u\L\1/g"
      ;;
+
     return 0
     esac
+
}
done
+
</pre>
shift $((OPTIND-1))
 
VERBOSE=${VERBOSE:-"N"}
 
  
 +
===Remove / rename a directory / file containing weird control characters===
 +
Use ls with -i to see inode listing
 +
<pre>
 +
ls -bali
 +
</pre>
 +
Use find with -inum to get the filename and -exec to remove it
 +
<pre>
 +
find . -inum <inode from ls listing> -exec rm -f {} \;
 +
</pre>
  
# --------------------------------
+
===Run a local script on a remote host===
# check we have required arguments
+
Doing it this way means we do not need to scp the shell over to the host before executing it!
# --------------------------------
+
<pre>
[[ -z $CMMND ]] && echo "Enter command to be executed like this: $0 -c 'ls -al'" && exit 1
+
ssh user@host 'sh' < your_script.sh
 +
</pre>
 +
First of all, this command is a redirection: your shell will open the file your_script.sh and feed it as input to the ssh command. ssh, in turn, will tunnel its stdin to the remote command, namely, sh instance. And sh without arguments reads its script from stdin. So we got sh instance, which is launched on remote host, but reads commands from your local file.
  
 
+
===Get a list of running instances - but only those started by the current user===
# ----------------------------
+
This is the way I wanted to do it but there's an issue. Where does that spare } character come from? Anyone?
# loop over the remote servers
+
<pre>
# ----------------------------
+
ps -ef | grep [p]mon | awk -v dbowner=$(id -un) '{ if ($1==dbowner) { gsub(/ora_pmon_/,"",$NF); print $NF; } }'
for server in ${serverlist}
+
</pre>
do
+
ps listing
    if [[ "$VERBOSE" == "Y" ]]; then
+
<pre>
        echo ${server} `date +'%d-%b-%Y %H:%M:%S'`
+
$ ps -ef | grep [p]mon
        echo "------------------------------------"
+
  oracle 13304024        1  0  Jun 07      - 2:39 ora_pmon_reportk
        set -x
+
  oracle 26018178        1  0  Jun 07      -  3:01 ora_pmon_dwh_perf
    fi
+
  oracle 29229432        1  0  Jun 07      - 2:30 ora_pmon_adso
    ssh ${server} "$CMMND"
+
oraebso 18022994        1  0  Jun 07      - 2:38 ora_pmon_EBSO
    set +x
+
  oracle 30278192        1  0  Jun 07      - 2:48 ora_pmon_owb112k
    [[ "$VERBOSE" == "Y" ]] && echo
 
done
 
 
</pre>
 
</pre>
to be investigated... this one might be cleverer than mine...
+
Results of above command
 
<pre>
 
<pre>
tmpdir=${TMPDIR:-/tmp}/pssh.$$
+
reportk
count=0
+
dwh_perf
while userhost; do
+
adso
    ssh -n -o BatchMode=yes ${userhost} 'uname -a' > ${tmpdir}/${userhost} 2>&1 &
+
}
    count=`expr $count + 1`
+
owb112k
done < userhost.lst
+
</pre>
while [ $count -gt 0 ]; do
+
Workaround 1. Send the ps listing to a file and work on it without pipes. Works but it's a bit long-winded especially as we have to clean up afterwards.
    wait $pids
+
<pre>
    count=`expr $count - 1`
+
ps -ef | grep [p]mon>/tmp/results.$$ 2>/dev/null; awk -v dbowner=$(id -un) '{ if ($1==dbowner) { gsub(/ora_pmon_/,"",$NF); print $NF; } }' /tmp/results.$$; rm -f /tmp/results.$$
done
+
</pre>
echo "Output for hosts are in $tmpdir"
+
Workaround 2. Don't like the grep -v but until I find out where that } is coming from..
 
+
<pre>
 
+
ps -ef | grep [p]mon | awk -v dbowner=$(id -un) '{ if ($1==dbowner) { gsub(/ora_pmon_/,"",$NF); print $NF; } }' | egrep -v 'grep|}|ASM'
 
</pre>
 
</pre>
  
 
+
===Return a list of Oracle databases running on a list of remote servers===
improved version...<br />
 
just escape double quotes and dollar signs...
 
 
<pre>
 
<pre>
 
#!/bin/ksh
 
#!/bin/ksh
# ==============================================================================
 
# Name        : dosh  (Distributed Oracle SHell)
 
# Description  : Runs a command on all Oracle servers
 
#
 
# Parameters  : h - displays help
 
#                v - verbose (default, like all unix commands is silent)
 
#                c - command to be executed
 
#
 
# Example      : ./dosh -v -c 'ls -al'
 
#
 
# Modification History
 
# ====================
 
# When      Who              What
 
# ========= ================= ==================================================
 
# 08-FEB-13 Stuart Barkley    Created
 
# 08-JUL-15 Stuart Barkley    Background execution mode
 
# ==============================================================================
 
# --------------------------------------------------------------------------
 
# this list of servers is generated by the DBAMON tool so will be up to date
 
# --------------------------------------------------------------------------
 
serverfile=/home/ibmtools/etc/oracle/oracle_servers
 
[[ -z "${serverfile}" ]] && echo "Server list ${serverfile} not found" && exit 1
 
  
serverlist=`cat ${serverfile} | sort -n | tr "\n" " "`
+
serverlist=`cat /home/tools/ini/system/oracle_servers | sort -n | tr "\n" " "`
 +
 
 +
if [ -z "${serverlist}" ]
 +
then
 +
    echo "no servers found" && exit 1
 +
fi
 +
 
  
 +
for server in ${serverlist}
 +
do
 +
    ssh ${server} "ps -ef | grep [o]ra_pmon_" >/tmp/${server}.dblist
 +
done
  
# -------------------------
+
for server in ${serverlist}
# get the arguments, if any
 
# -------------------------
 
while getopts "hbvc:" OPT
 
 
do
 
do
     case "$OPT" in
+
     cat /tmp/${server}.dblist | awk -F_ -v SRV=${server} 'BEGIN {print SRV ":"} {print $NF}' | tr "\n" " "
    h) echo "\nUsage: $0 [-b] [-v] [-h] -c '<command_to_be_executed_remotely>'\n";
+
     echo
      exit;
 
      ;;
 
    b) BACKGROUND="Y";
 
      ;;
 
    v) VERBOSE="Y";
 
      ;;
 
    c) CMMND=$OPTARG;
 
      ;;
 
    *) echo "\nUsage: $0 [-b] [-v] [-h] -c '<command_to_be_executed_remotely>'\n";
 
      exit;
 
      ;;
 
     esac
 
 
done
 
done
shift $((OPTIND-1))
+
</pre>
VERBOSE=${VERBOSE:-"N"}
 
  
 +
===Clever trick to check whether SQL output needs sending to someone===
 +
Using an exit status from SQL*Plus back to the shell so we can decide what to do.  Nice one!
 +
<pre>
 +
#!/bin/bash
 +
tempfile=/tmp/audit_locked_accounts_$ORACLE_SID.txt
  
# --------------------------------
+
# Start sqlplus and check for locked accounts
# check we have required arguments
+
sqlplus -S "/ as sysdba" << EOF > $tempfile
# --------------------------------
+
set pages 0
[[ -z $CMMND ]] && echo "Enter command to be executed like this: $0 -c 'ls -al'" && exit 1
+
select 'The following accounts were found to be unlocked and should not be'
 +
from dual;
  
 +
def exit_status = 0
 +
col xs new_value exit_status
  
# ---------------------------------
+
select username
# put the thing to be run in a file
+
,      account_status
# ---------------------------------
+
,      1 as xs
printf "%s\n" "$CMMND" > /tmp/dosh.$$
+
from  dba_users
 +
where  account_status != 'LOCKED'
 +
and    username in ('HR', 'SCOTT', 'OUTLN', 'MDSYS', 'CTXSYS')
 +
/
 +
exit &exit_status
 +
EOF
  
 
+
# If the exit status of sqlplus was not 0 then we will send an email
# ----------------------------
+
if [ $? != 0 ]; then
# loop over the remote servers
+
    mail -s "Accounts Unlocked in $ORACLE_SID" oracle < $tempfile
# ----------------------------
+
fi
for server in ${serverlist}
 
do
 
    if [[ "$VERBOSE" == "Y" ]]; then
 
        printf "%s\n" ${server} `date +'%d-%b-%Y %H:%M:%S'`
 
        printf "%s\n" "------------------------------------"
 
        set -x
 
    fi
 
    scp -q /tmp/dosh.$$ ${server}:/tmp/
 
    if [[ "$BACKGROUND" == "Y" ]]; then
 
        ssh -n -o BatchMode=yes ${server} "ksh /tmp/dosh.$$; rm -f /tmp/dosh.$$"> /tmp/dosh_${server}.out 2>&1 &
 
    else
 
        ssh -n -o BatchMode=yes ${server} "ksh /tmp/dosh.$$; rm -f /tmp/dosh.$$"
 
    fi
 
    set +x
 
    [[ "$VERBOSE" == "Y" ]] && echo
 
done
 
rm -f /tmp/dosh.$$
 
 
 
[[ "$BACKGROUND" == "Y" ]] && printf "%s\n" "Type 'ls -altr /tmp/dosh*out' to see output from the commands"
 
 
</pre>
 
</pre>
  
===How can a shell script find out what directory it is in?===
+
===Check RMAN logfiles for errors from cron every day===
 
<pre>
 
<pre>
DIR="$(cd "$(dirname "$0")" && pwd)"
+
00 09 * * * /home/tools/scripts/oracle/dosh 'find /home/tools/logs/rman -name "*online.log" -mtime -1 -exec sed -ne "/^RMAN-/,/^$/p" {} \\; -ls' | mailx
 +
-s 'RMAN errors last night' [email protected]
 +
</pre>
 +
<pre>
 +
/home/ibmtools/scripts/oracle/dosh 'find /oracle/export -name "expdp*log" -mtime -1 -exec grep ORA- {} \; -ls' | mailx -s 'Datapump errors for Baxter last night' [email protected]
 
</pre>
 
</pre>
 
+
===An alternative to getopts===
===Array processing===
+
These methods have the advantage of allowing arguments of any length not just 1 character
 
<pre>
 
<pre>
array=(1 2 3)
+
countArgs=$#
unset array[2]
+
while [[ $# -gt 0 ]]
echo ${array[2]}          # null
+
do
indices=(${!array[@]})   # create an array of the indices of "array"
+
    idx1=$($ECHO $1|$GREP "="|wc -l)
size=${#indices[@]}      # the size of "array" is the number of indices into it
+
    if [[ $idx1 -gt 0 ]]; then
size=${#array[@]}        # same
+
        key=$($ECHO $1|$CUT -d '=' -f 1)
echo ${array[@]: -1}      # you can use slices to get array elements, -1 is the last one, etc.
+
        value=$($ECHO $1|$CUT -d '=' -f 2)
for element in ${array[@]}; do    # iterate over the array without an index
+
    else
 +
        key=$($ECHO $1|$CUT -d '=' -f 1)
 +
        idx2=$($ECHO $1|$GREP "^-"|wc -l)
 +
        if [[ $idx2 -eq 0 ]]; then
 +
            $ECHO -e "\n ERROR: $1 is an unsupported argument passed to agentDeploy.sh.\n" 
 +
            usage
 +
            exit 1
 +
        fi
 +
    fi
  
for index in ${indices[@]}        # iterate over the array WITH an index
+
    case "$key" in
do
+
    -help)
     echo "Index: ${index}, Element: ${array[index]}"
+
        if [[ $upgradeFlag ]]; then
 +
            upgradeUsage
 +
        else
 +
            freshUsage
 +
        fi
 +
        exit 0;;
 +
    AGENT_BASE_DIR)
 +
        agentBaseDir=$($ECHO $value|$SED 's/\/$//')
 +
        checkBaseFlag=TRUE;;
 +
    OMS_HOST)
 +
        omsHost=$value
 +
        checkOMSHost=TRUE;;
 +
     EM_UPLOAD_PORT)
 +
        omsPort=$value
 +
        checkOMSPort=TRUE;;
 +
    AGENT_INSTANCE_HOME)
 +
        instHome=$($ECHO $value | $SED 's/\/$//');;
 +
    AGENT_REGISTRATION_PASSWORD)
 +
        pswd=$value;;
 +
    s_encrSecurePwd)
 +
        pswd=$value;; 
 +
    RESPONSE_FILE)
 +
        rspFlag=TRUE 
 +
        rspLoc=$value;;
 +
    OLD_AGENT_VERSION)
 +
        oldAgentVersion=$value;;           
 +
    OLDHOME)
 +
        oldHome=$value;;   
 +
    -debug)
 +
        debugSwitch=TRUE;;
 +
    -forceConfigure)
 +
        forceFlag=TRUE;;
 +
    -configOnly)
 +
        configFlag=TRUE   
 +
        validationFlag=TRUE;;
 +
    -agentImageLocation)
 +
        archiveLoc=$value
 +
        checkArchiveFlag=TRUE;;
 +
    -invPtrLoc) shift
 +
        ptrLoc=$1;;
 +
    -Upgrade)
 +
        UpgradeFlag=TRUE
 +
        validFlag=TRUE;;
 +
    INVENTORY_LOCATION)
 +
        validFlag=TRUE;;
 +
    b_forceInstCheck)
 +
        validFlag=TRUE
 +
        forcefullFlag=TRUE;;
 +
    -prereqOnly)
 +
        validationFlag=TRUE
 +
        prereqFlag=TRUE;;
 +
    -executeRootsh)
 +
        validFlag=TRUE;;
 +
    *)  idx=$($ECHO $1|$GREP "^-"|wc -l)
 +
        if [[ $idx -eq 0 ]]; then
 +
            validFlag=TRUE
 +
        else
 +
            $ECHO -e "\n ERROR: Invalid argument $key passed."
 +
            usage
 +
            exit 1         
 +
        fi
 +
    esac
 +
    shift
 
done
 
done
  
for index in ${!array[@]}        # iterate over the array WITH an index, directly
+
</pre>
 +
another way - found in /etc/init.d/functions (daemon function) in Fedora
 +
<pre>
 +
    while [ "$1" != "${1##[-+]}" ]; do
 +
        case $1 in
 +
        '')
 +
            echo $"$0: Usage: daemon [+/-nicelevel] {program}" "[arg1]..."
 +
            return 1
 +
            ;;
 +
        --check)
 +
            base=$2
 +
            gotbase="yes"
 +
            shift 2
 +
            ;;
 +
        --check=?*)
 +
            base=${1#--check=}
 +
            gotbase="yes"
 +
            shift
 +
            ;;
 +
        --user)
 +
            user=$2
 +
            shift 2
 +
            ;;
 +
         --user=?*)
 +
            user=${1#--user=}
 +
            shift
 +
            ;;
 +
        --pidfile)
 +
            pid_file=$2
 +
            shift 2
 +
            ;;
 +
        --pidfile=?*)
 +
            pid_file=${1#--pidfile=}
 +
            shift
 +
            ;;
 +
        --force)
 +
            force="force"
 +
            shift
 +
            ;;
 +
        [-+][0-9]*)
 +
            nice="nice -n $1"
 +
            shift
 +
            ;;
 +
        *)
 +
            echo $"$0: Usage: daemon [+/-nicelevel] {program}" "[arg1]..."
 +
            return 1
 +
            ;;
 +
      esac
 +
    done
 +
</pre>
 +
another way - found in adstrtal.sh (middleware start script for EBS)
 +
<pre>
 +
#
 +
# Parse Arguments
 +
#
 +
 
 +
for nxtarg in $*
 +
do
 +
  arg=`echo $nxtarg | sed 's/^//'`
  
array+=("new element")   # append a new element without referring to an index
+
  case $arg in
((counter++))            # shorter than ((counter=counter+1)) or ((counter+=1))
+
    -secureapps)    if test "$secureapps" = "" ; then
if [[ $var == 3 ]]        # you can use the more "natural" comparison operators inside double square brackets
+
                      secureapps=$arg
while [[ $var < 11 ]]    # another example
+
                    else
echo ${array[${index}-1]  # math inside an array subscript
+
                      echo "$0: Duplicate Argument passed : $arg"
 +
                      usage
 +
                    fi
 +
                ;;
 +
    -nodbchk)       if test "$nodbchk" = "" ; then
 +
                      nodbchk=$arg
 +
                    else
 +
                      echo "$0: Duplicate Argument passed : $arg"
 +
                      usage
 +
                    fi
 +
                ;;
 +
    -nopromptmsg)   if test "$nopromptmsg" = "" ; then
 +
                      nopromptmsg=$arg
 +
                    else
 +
                      echo "$0: Duplicate Argument passed : $arg"
 +
                      usage
 +
                    fi
 +
                ;;
 +
    *)             if test "$unpw" = "" ; then
 +
                      unpw=$arg
 +
                    else
 +
                      echo "$0: Duplicate Argument passed : $arg"
 +
                      usage
 +
                    fi
 +
  esac
 +
done
 
</pre>
 
</pre>
===Send an email by talking directly to an smtp server===
+
and another in adautocfg.sh
 
<pre>
 
<pre>
#!/bin/bash
+
for myarg in $*
telnet smtp.domain.com 25 <<EOTXT>>/tmp/smtp.log
+
do
HELO me.domain.com
 
MAIL FROM:<[email protected]>
 
 
DATA
 
From: Stuart <[email protected]>
 
 
Subject: testing smtp email
 
  
Hello, this should appear in the body
+
  arg=`echo $myarg | sed 's/^-//'`
.
+
  case $arg in
QUIT
+
    appspass=*)
EOTXT
+
            appspass=`echo $arg | sed 's/appspass=//g'`
 +
            shift
 +
            ;;
 +
    nocustom)
 +
            myparams="$myparams $arg"
 +
            shift
 +
            ;;
 +
    noversionchecks)
 +
            myparams="$myparams $arg"
 +
            shift
 +
            ;;
 +
    promptmsg=*)
 +
            promptmsg=`echo $arg | sed 's/promptmsg=//g'`
 +
            shift
 +
            ;;
 +
        *)  echo "$0: unrecognized action specified"
 +
            exit 1
 +
  esac
 +
done
 
</pre>
 
</pre>
===Send an email by talking directly to an smtp server via file descriptor (no telnet! this time), adding authentication===
+
 
 +
===Run a script on multiple servers===
 
<pre>
 
<pre>
#!/bin/bash
+
#!/bin/ksh
 
+
# ==============================================================================
 +
# Name        : dosh  (Distributed Oracle SHell)
 +
# Description  : Runs a command on all Oracle servers
 
#
 
#
# mail.sh
+
# Parameters  : h - displays help
 +
#                v - verbose (default, like all unix commands is silent)
 +
#                c - command to be executed
 
#
 
#
# 2008 - Mike Golvach - eggi@comcast.net
+
# Example      : ./dosh -v -c 'ls -al'
# 2010 - Rayber
 
#
 
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
 
 
#
 
#
 +
# Modification History
 +
# ====================
 +
# When      Who              What
 +
# ========= ================= ==================================================
 +
# 08-FEB-13 Stuart Barkley    Created
 +
# ==============================================================================
  
if [ $# -ne 7 ]
+
# --------------------------------------------------------------------------
then
+
# this list of servers is generated by the DBAMON tool so will be up to date
echo "Usage: $0 FromAdress ToAdress Domain MailServer MailTextFile AuthEmail AuthPass"
+
# --------------------------------------------------------------------------
exit 1
+
serverfile=/home/ibmtools/etc/oracle/oracle_servers
fi
+
[[ -z "${serverfile}" ]] && echo "Server list ${serverfile} not found" && exit 1
  
from=$1
+
serverlist=`cat ${serverfile} | sort -n | tr "\n" " "`
to=$2
 
domain=$3
 
mailserver=$4
 
mailtext=$5
 
authemail=`echo $6|openssl enc -base64|awk 'sub("..$", "")'`
 
authpass=`echo $7|openssl enc -base64|awk 'sub("..$", "")'`
 
  
if [ ! -f $mailtext ]
 
then
 
echo "Cannot find your mail text file. Exiting..."
 
exit 1
 
fi
 
  
exec 9<>/dev/tcp/$mailserver/25
+
# -------------------------
echo "HELO $domain" >&9
+
# get the arguments, if any
read -r temp <&9
+
# -------------------------
echo "$temp"
+
while getopts "hvc:" OPT
echo "auth login" >&9
+
do
read -r temp <&9
+
    case "$OPT" in
echo "$authemail" >&9
+
    h) echo "\nUsage: $0 [-v] [-h] -c '<command_to_be_executed_remotely>'\n";
read -r temp <&9
+
      exit;
echo "$authpass" >&9
+
      ;;
read -r temp <&9
+
    v) VERBOSE="Y";
echo "Mail From: $from" >&9
+
      ;;
read -r temp <&9
+
    c) CMMND=$OPTARG;
echo "$temp"
+
      ;;
echo "Rcpt To: $to" >&9
+
    *) echo "\nUsage: $0 [-v] [-h] -c '<command_to_be_executed_remotely>'\n";
read -r temp <&9
+
      exit;
echo "$temp"
+
      ;;
echo "Data" >&9
+
    esac
read -r temp <&9
+
done
echo "$temp"
+
shift $((OPTIND-1))
cat $mailtext >&9
+
VERBOSE=${VERBOSE:-"N"}
echo "." >&9
+
 
read -r temp <&9
 
echo "$temp"
 
echo "quit" >&9
 
read -r temp <&9
 
echo "$temp"
 
9>&-
 
9<&-
 
echo "All Done Sending Email. See above for errors"
 
exit 0
 
</pre>
 
  
=== rsync examples===
+
# --------------------------------
Also see [[Distribute files to multiple servers using rsync and ssh]]
+
# check we have required arguments
<pre>
+
# --------------------------------
#!/bin/sh
+
[[ -z $CMMND ]] && echo "Enter command to be executed like this: $0 -c 'ls -al'" && exit 1
ssh  <remote_host> '/bin/mkdir -p /etc /etc/rc.config.d /etc/security /etc/mail'
 
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/passwd /etc/passwd.post /etc/group /etc/hosts /etc/services /etc/resolv.conf /etc/exclude.rootvg <remote_host>:/etc
 
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/hosts.allow.xcat <remote_host>:/etc/hosts.allow
 
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/rc.config.d/sap <remote_host>:/etc/rc.config.d
 
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/security/group /etc/security/limits /etc/security/login.cfg /etc/security/passwd /etc/security/user <remote_host>:/etc/security
 
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/mail/sendmail.cf <remote_host>:/etc/mail
 
  
rsync -av --progress /home/ibmtools/scripts/oracle/* benouerp07:/home/ibmtools/scripts/oracle/
 
</pre>
 
  
===Handy aliases===
+
# ----------------------------
Strip out comments and blank lines from a file
+
# loop over the remote servers
<pre>
+
# ----------------------------
alias strip='grep -Ev '\''^(#|$)'\'''
+
for server in ${serverlist}
</pre>
+
do
Does a ps and a grep
+
    if [[ "$VERBOSE" == "Y" ]]; then
<pre>
+
        echo ${server} `date +'%d-%b-%Y %H:%M:%S'`
alias psg='ps -ef | grep -v $$ | grep -i '
+
        echo "------------------------------------"
 +
        set -x
 +
    fi
 +
    ssh ${server} "$CMMND"
 +
    set +x
 +
    [[ "$VERBOSE" == "Y" ]] && echo
 +
done
 
</pre>
 
</pre>
A handy way of listing subdirectories and their files
+
to be investigated... this one might be cleverer than mine...
 
<pre>
 
<pre>
alias filetree="find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'"
+
tmpdir=${TMPDIR:-/tmp}/pssh.$$
 +
count=0
 +
while userhost; do
 +
    ssh -n -o BatchMode=yes ${userhost} 'uname -a' > ${tmpdir}/${userhost} 2>&1 &
 +
    count=`expr $count + 1`
 +
done < userhost.lst
 +
while [ $count -gt 0 ]; do
 +
    wait $pids
 +
    count=`expr $count - 1`
 +
done
 +
echo "Output for hosts are in $tmpdir"
 +
 
 +
 
 
</pre>
 
</pre>
Watch progress of a copy
+
 
 +
 
 +
improved version...<br />
 +
just escape double quotes and dollar signs...
 
<pre>
 
<pre>
alias cpProgress="rsync --progress -ravz"
+
#!/bin/ksh
</pre>
+
# ==============================================================================
Reboots Linksys router<pre>
+
# Name        : dosh  (Distributed Oracle SHell)
alias rebootlinksys="curl -u 'admin:password' 'http://192.168.1.2/setup.cgi?todo=reboot'"
+
# Description  : Runs a command on all Oracle servers
</pre>
+
#
Nice one for bash. Colour codes the prompt depending on the outcome of the previous command
+
# Parameters  : h - displays help
<pre>
+
#                v - verbose (default, like all unix commands is silent)
bash_prompt_command()
+
#                c - command to be executed
{
+
#
    RTN=$?
+
# Example      : ./dosh -v -c 'ls -al'
    prevCmd=$(prevCmd $RTN)
+
#
}
+
# Modification History
PROMPT_COMMAND=bash_prompt_command
+
# ====================
prevCmd()
+
# When      Who              What
{
+
# ========= ================= ==================================================
    if [ $1 == 0 ] ; then
+
# 08-FEB-13 Stuart Barkley    Created
        echo $GREEN
+
# 08-JUL-15 Stuart Barkley    Background execution mode
    else
+
# ==============================================================================
        echo $RED
+
# --------------------------------------------------------------------------
    fi
+
# this list of servers is generated by the DBAMON tool so will be up to date
}
+
# --------------------------------------------------------------------------
if [ $(tput colors) -gt 0 ] ; then
+
serverfile=/home/ibmtools/etc/oracle/oracle_servers
     RED=$(tput setaf 1)
+
[[ -z "${serverfile}" ]] && echo "Server list ${serverfile} not found" && exit 1
     GREEN=$(tput setaf 2)
+
 
     RST=$(tput op)
+
serverlist=`cat ${serverfile} | sort -n | tr "\n" " "`
fi
+
 
export PS1="\[\e[36m\]\u.\h.\W\[\e[0m\]\[\$prevCmd\]>\[$RST\]"
+
 
</pre>
+
# -------------------------
Mmmm, to be looked into. Executes remote commands on a unix box using curl.
+
# get the arguments, if any
<pre>
+
# -------------------------
#/bin/sh
+
while getopts "hbvc:" OPT
#
+
do
# WAG320N-HACK
+
    case "$OPT" in
# Ver. 1.0
+
    h) echo "\nUsage: $0 [-b] [-v] [-h] -c '<command_to_be_executed_remotely>'\n";
# 12/09/2010
+
      exit;
#
+
      ;;
# This program is free software: you can redistribute it and/or modify
+
     b) BACKGROUND="Y";
# it under the terms of the GNU General Public License as published by
+
      ;;
# the Free Software Foundation, either version 3 of the License, or
+
     v) VERBOSE="Y";
# (at your option) any later version.
+
      ;;
#
+
     c) CMMND=$OPTARG;
# This program is distributed in the hope that it will be useful,
+
      ;;
# but WITHOUT ANY WARRANTY; without even the implied warranty of
+
    *) echo "\nUsage: $0 [-b] [-v] [-h] -c '<command_to_be_executed_remotely>'\n";
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+
      exit;
# GNU General Public License for more details.
+
      ;;
#
+
    esac
# You should have received a copy of the GNU General Public License
+
done
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
shift $((OPTIND-1))
 +
VERBOSE=${VERBOSE:-"N"}
  
# Set username and password in the form of "username:password"
 
# example: "admin:admin"
 
my_access="admin:admin"
 
  
# Parameters test
+
# --------------------------------
if [ -z "$1" ]
+
# check we have required arguments
then
+
# --------------------------------
  echo "wag320n-hack.sh: missing remote command"
+
[[ -z $CMMND ]] && echo "Enter command to be executed like this: $0 -c 'ls -al'" && exit 1
  echo "usage: wag320n-hack.sh <remote command>"
+
 
  echo "example: wag320n-hack.sh /bin/ls -la /usr/sbin"
 
  echo "Note: always use full path"
 
  echo ""
 
  echo "wag320n-hack.sh - Ver. 1.0 - 12/09/2010"
 
  echo "Licensed under GPL V. 3"
 
  echo ""
 
  exit 0
 
fi
 
  
# Get the command
+
# ---------------------------------
my_command="ping_size="'$('"$@"' 1>&2)'
+
# put the thing to be run in a file
 +
# ---------------------------------
 +
printf "%s\n" "$CMMND" > /tmp/dosh.$$
  
curl -s -G -u "$my_access" --data-urlencode 'todo=ping_test' --data-urlencode 'this_file=Diagnostics.htm' --data-urlencode 'next_file=Ping.htm' --data-urlencode 'c4_ping_ipaddr=192.168.1.1' --data-urlencode 'ping_timeout=5000' --data-urlencode 'ping_interval=1000' --data-urlencode 'ping_number=1' --data-urlencode "$my_command" http://192.168.1.1/setup.cgi | sed -e '/HTTP\/1.0 200 OK/q'
 
</pre>
 
  
===How to configure SSH with public/private keys===
+
# ----------------------------
* [http://www.unixpeople.com/HOWTO/configuring.ssh.html unixpeople.com]
+
# loop over the remote servers
===Use SSH config file===
+
# ----------------------------
<pre>
+
for server in ${serverlist}
Host server10
+
do
  Hostname 1.2.3.4
+
    if [[ "$VERBOSE" == "Y" ]]; then
  IdentityFile ~/.ssh/id_dsa
+
        printf "%s\n" ${server} `date +'%d-%b-%Y %H:%M:%S'`
  user foobar
+
        printf "%s\n" "------------------------------------"
  Port 30000
+
        set -x
  ForwardX11Trusted yes
+
    fi
  TCPKeepAlive yes
+
    scp -q /tmp/dosh.$$ ${server}:/tmp/
 +
    if [[ "$BACKGROUND" == "Y" ]]; then
 +
        ssh -n -o BatchMode=yes ${server} "ksh /tmp/dosh.$$; rm -f /tmp/dosh.$$"> /tmp/dosh_${server}.out 2>&1 &
 +
    else
 +
        ssh -n -o BatchMode=yes ${server} "ksh /tmp/dosh.$$; rm -f /tmp/dosh.$$"
 +
    fi
 +
    set +x
 +
    [[ "$VERBOSE" == "Y" ]] && echo
 +
done
 +
rm -f /tmp/dosh.$$
 +
 
 +
[[ "$BACKGROUND" == "Y" ]] && printf "%s\n" "Type 'ls -altr /tmp/dosh*out' to see output from the commands"
 
</pre>
 
</pre>
then just connect using
+
 
 +
===How can a shell script find out what directory it is in?===
 +
basename $0 does not always give the desired answer (might give "./"!
 
<pre>
 
<pre>
ssh server10
+
DIR="$(cd "$(dirname "$0")" && pwd)"
 
</pre>
 
</pre>
  
===A decent sed tutorial===
+
===Array processing===
From [http://www.grymoire.com/Unix/Sed.html grymoire.com]
 
===A decent korn/bash shell tutorial===
 
From [http://www.dartmouth.edu/~rc/classes/ksh/print_pages.shtml dartmouth.edu]
 
Reproduced here just in case it disappears!
 
[[Advanced shell scripting]]
 
 
 
===trap===
 
 
<pre>
 
<pre>
     Example Handling Traps With ksh - Discussion of the kill command
+
array=(1 2 3)
 +
unset array[2]
 +
echo ${array[2]}          # null
 +
indices=(${!array[@]})    # create an array of the indices of "array"
 +
size=${#indices[@]}      # the size of "array" is the number of indices into it
 +
size=${#array[@]}        # same
 +
echo ${array[@]: -1}     # you can use slices to get array elements, -1 is the last one, etc.
 +
for element in ${array[@]}; do    # iterate over the array without an index
  
 +
for index in ${indices[@]}        # iterate over the array WITH an index
 +
do
 +
    echo "Index: ${index}, Element: ${array[index]}"
 +
done
  
EXAMPLE TEMPLATE:
+
for index in ${!array[@]}        # iterate over the array WITH an index, directly
  
 +
array+=("new element")    # append a new element without referring to an index
 +
((counter++))            # shorter than ((counter=counter+1)) or ((counter+=1))
 +
if [[ $var == 3 ]]        # you can use the more "natural" comparison operators inside double square brackets
 +
while [[ $var < 11 ]]    # another example
 +
echo ${array[${index}-1]  # math inside an array subscript
 +
</pre>
 +
===Send an email by talking directly to an smtp server===
 +
<pre>
 +
#!/bin/bash
 +
telnet smtp.domain.com 25 <<EOTXT>>/tmp/smtp.log
 +
HELO me.domain.com
 +
MAIL FROM:<[email protected]>
 +
 +
DATA
 +
From: Stuart <[email protected]>
 +
 +
Subject: testing smtp email
  
PRODUCT:    HP-UX 11iV1 Version B.11.11
+
Hello, this should appear in the body
            HP Tru64 V5.1B PK4
+
.
            Sun/Solaris SunOS V5.8
+
QUIT
            Linux 2.6 kernel
+
EOTXT
 +
</pre>
 +
===Send an email by talking directly to an smtp server via file descriptor (no telnet! this time), adding authentication===
 +
<pre>
 +
#!/bin/bash
  
 +
#
 +
# mail.sh
 +
#
 +
# 2008 - Mike Golvach - [email protected]
 +
# 2010 - Rayber
 +
#
 +
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
 +
#
  
COMPONENT: ksh
+
if [ $# -ne 7 ]
 +
then
 +
echo "Usage: $0 FromAdress ToAdress Domain MailServer MailTextFile AuthEmail AuthPass"
 +
exit 1
 +
fi
  
 +
from=$1
 +
to=$2
 +
domain=$3
 +
mailserver=$4
 +
mailtext=$5
 +
authemail=`echo $6|openssl enc -base64|awk 'sub("..$", "")'`
 +
authpass=`echo $7|openssl enc -base64|awk 'sub("..$", "")'`
  
SOURCE:    Philippe Vouters
+
if [ ! -f $mailtext ]
            Fontainebleau/France
+
then
 +
echo "Cannot find your mail text file. Exiting..."
 +
exit 1
 +
fi
  
 +
exec 9<>/dev/tcp/$mailserver/25
 +
echo "HELO $domain" >&9
 +
read -r temp <&9
 +
echo "$temp"
 +
echo "auth login" >&9
 +
read -r temp <&9
 +
echo "$authemail" >&9
 +
read -r temp <&9
 +
echo "$authpass" >&9
 +
read -r temp <&9
 +
echo "Mail From: $from" >&9
 +
read -r temp <&9
 +
echo "$temp"
 +
echo "Rcpt To: $to" >&9
 +
read -r temp <&9
 +
echo "$temp"
 +
echo "Data" >&9
 +
read -r temp <&9
 +
echo "$temp"
 +
cat $mailtext >&9
 +
echo "." >&9
 +
read -r temp <&9
 +
echo "$temp"
 +
echo "quit" >&9
 +
read -r temp <&9
 +
echo "$temp"
 +
9>&-
 +
9<&-
 +
echo "All Done Sending Email. See above for errors"
 +
exit 0
 +
</pre>
  
LOW COST HIGH-TECH PRODUCTS: http://techno-star.fr
+
=== rsync examples===
 
+
Also see [[Distribute files to multiple servers using rsync and ssh]]
 
+
<pre>
OVERVIEW:
+
#!/bin/sh
 
+
ssh <remote_host> '/bin/mkdir -p /etc /etc/rc.config.d /etc/security /etc/mail'
The ksh script below shows how to eventually handle traps in the situation
+
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/passwd /etc/passwd.post /etc/group /etc/hosts /etc/services /etc/resolv.conf /etc/exclude.rootvg <remote_host>:/etc
where someone might try to kill a script by killing individual commands run
+
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/hosts.allow.xcat <remote_host>:/etc/hosts.allow
by that script or the entire process group a script is running in. The kill
+
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/rc.config.d/sap <remote_host>:/etc/rc.config.d
command (usually a shell builtin) may be used to send a signal to a process
+
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/security/group /etc/security/limits /etc/security/login.cfg /etc/security/passwd /etc/security/user <remote_host>:/etc/security
group (with the -<pid> syntax) or an individual process. The example ksh
+
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/mail/sendmail.cf <remote_host>:/etc/mail
script below runs /bin/sleep as the foreground process, the example ksh
 
scripts immediately returns when the /bin/sleep process has terminated. Most
 
signals sent to the shell are ignored until after the foreground process
 
terminates. This is in order to avoid creating zombie processes. Therefore a
 
kill <pid> on the example ksh script waits for the termination of the
 
/bin/sleep process.
 
 
 
The status value $? in the trap refers to the exit status of the command to run
 
and therefore is the exit status of the /bin/sleep process. The called function
 
in the trap handler shows how to correctly examine the effect of the kill
 
command on the shell or it's children.
 
  
To examine the value of $? in a trap handler means that you must understand what
+
rsync -av --progress /home/ibmtools/scripts/oracle/* benouerp07:/home/ibmtools/scripts/oracle/
it can be set and how different signals delivered to either the shell or the
+
</pre>
foreground process (or the process group) might affect the value of $?.
 
  
The example shell script prints $? using echo but it does not perform tests on
+
===Handy aliases===
the value of $?. For a complete solution when attempting to trap signals in a  
+
Strip out comments and blank lines from a file
shell you would also need code that examined the value of $? after the  
+
<pre>
foreground process had completed.
+
alias strip='grep -Ev '\''^(#|$)'\'''
 
+
</pre>
 
+
Does a ps and a grep
*** CAUTION ***
+
<pre>
 
+
alias psg='ps -ef | grep -v $$ | grep -i '
This sample script has been tested using HP-UX B.11.11, HP Tru64 V5.1B PK4,  
+
</pre>
SunOS V5.8 and Fedora Core 4 (homed version of Red Hat Linux).  However, we
+
Getting a decent listing of filesystem space available. It is ordered such that the filesystems with no space left are at the end.
cannot guarantee its effectiveness because of the possibility of error in
+
<pre>
transmitting or implementing it. It is meant to be used as a template for
+
OS=$(uname -s)
writing your own scripts, and may require modification for use on your system.
+
[[ "$OS" == "SunOS" ]] && alias dfg='df -h|sed -e '1d'|sort -n -k5|awk '\'' BEGIN {printf("%-35s%-10s%-10s%-6s%-30s\n","Filesystem","Total","Free","%Used","Mounted on")} {printf("%-35s%-10s%-10s%-6s%-30s\n",$1,$2,$4,$5,$6)}'\'''
 
+
[[ "$OS" == "AIX" ]]  && alias dfg='df -g|sed -e '1d'|sort -n -k4|awk '\'' BEGIN {printf("%-35s%-10s%-10s%-6s%-30s\n","Filesystem","Total GB","Free","%Used","Mounted on")} {printf("%-35s%-10s%-10s%-6s%-30s\n",$1,$2,$3,$4,$7)}'\'''
 
+
</pre>
SCRIPT NOTES:
+
A handy way of listing subdirectories and their files
 
+
<pre>
To notice that the ksh script and /bin/sleep share the same process group
+
alias filetree="find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'"
identifier (PGID), issue the following commands:
+
</pre>
 
+
Watch progress of a copy
[philippe@victor ~]$ who
+
<pre>
philippe :0           Jan 10 10:16
+
alias cpProgress="rsync --progress -ravz"
philippe pts/1       Jan 10 21:30 (:0.0)
+
</pre>
philippe pts/2        Jan 10 21:30 (:0.0)
+
Reboots Linksys router<pre>
[philippe@victor ~]$ tty
+
alias rebootlinksys="curl -u 'admin:password' 'http://192.168.1.2/setup.cgi?todo=reboot'"
/dev/pts/1
+
</pre>
[philippe@victor ~]$ ps -j -t pts/2
+
Nice one for bash. Colour codes the prompt depending on the outcome of the previous command
  PID  PGID  SID TTY          TIME CMD
+
<pre>
11072 11072 11072 pts/2    00:00:00 bash
+
bash_prompt_command()
11113 11113 11072 pts/2    00:00:00 ksh
+
{
11116 11113 11072 pts/2    00:00:00 sleep
+
    RTN=$?
 
+
    prevCmd=$(prevCmd $RTN)
In this case sending kill -INT -11113 will send SIGINT to the process group
+
}
11113. Both of the ksh and sleep processes are contained within this process
+
PROMPT_COMMAND=bash_prompt_command
group.
+
prevCmd()
 
+
{
Important Note:
+
    if [ $1 == 0 ] ; then
 
+
        echo $GREEN
On HP-UX, you have to $ export UNIX95=1 in order to be able to use the
+
    else
-j option of the ps command.
+
        echo $RED
 
+
    fi
 
+
}
SCRIPT:
+
if [ $(tput colors) -gt 0 ] ; then
 
+
    RED=$(tput setaf 1)
                            COPYRIGHT (C) 2005 BY
+
    GREEN=$(tput setaf 2)
                              HEWLETT-PACKARD COMPANY
+
    RST=$(tput op)
                                ALL RIGHTS RESERVED.
+
fi
 +
export PS1="\[\e[36m\]\u.\h.\W\[\e[0m\]\[\$prevCmd\]>\[$RST\]"
 +
</pre>
 +
Mmmm, to be looked into. Executes remote commands on a unix box using curl.
 +
<pre>
 +
#/bin/sh
 +
#
 +
# WAG320N-HACK
 +
# Ver. 1.0
 +
# 12/09/2010
 +
#
 +
# This program is free software: you can redistribute it and/or modify
 +
# it under the terms of the GNU General Public License as published by
 +
# the Free Software Foundation, either version 3 of the License, or
 +
# (at your option) any later version.
 +
#
 +
# This program is distributed in the hope that it will be useful,
 +
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 +
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +
# GNU General Public License for more details.
 +
#
 +
# You should have received a copy of the GNU General Public License
 +
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
    THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
+
# Set username and password in the form of "username:password"
    ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE INCLUSION
+
# example: "admin:admin"
    OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY OTHER COPIES
+
my_access="admin:admin"
    THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER
 
    PERSON.  NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
 
  
    THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
+
# Parameters test
    SHOULD NOT BE CONSTRUED AS A COMMITMENT BY HEWLETT-PACKARD COMPANY.
+
if [ -z "$1" ]
 +
then
 +
  echo "wag320n-hack.sh: missing remote command"
 +
  echo "usage: wag320n-hack.sh <remote command>"
 +
  echo "example: wag320n-hack.sh /bin/ls -la /usr/sbin"
 +
  echo "Note: always use full path"
 +
  echo ""
 +
  echo "wag320n-hack.sh - Ver. 1.0 - 12/09/2010"
 +
  echo "Licensed under GPL V. 3"
 +
  echo ""
 +
  exit 0
 +
fi
  
    HP ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
+
# Get the command
    SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY HP.
+
my_command="ping_size="'$('"$@"' 1>&2)'
  
    NO RESPONSIBILITY IS ASSUMED FOR THE USE OR RELIABILITY OF SOFTWARE
+
curl -s -G -u "$my_access" --data-urlencode 'todo=ping_test' --data-urlencode 'this_file=Diagnostics.htm' --data-urlencode 'next_file=Ping.htm' --data-urlencode 'c4_ping_ipaddr=192.168.1.1' --data-urlencode 'ping_timeout=5000' --data-urlencode 'ping_interval=1000' --data-urlencode 'ping_number=1' --data-urlencode "$my_command" http://192.168.1.1/setup.cgi | sed -e '/HTTP\/1.0 200 OK/q'
    ON EQUIPMENT THAT IS NOT SUPPLIED BY HEWLETT-PACKARD COMPANY.
+
</pre>
  
    SUPPORT FOR THIS SOFTWARE IS NOT COVERED UNDER ANY HP SOFTWARE
+
===How to configure SSH with public/private keys===
    PRODUCT SUPPORT CONTRACT, BUT MAY BE PROVIDED UNDER THE TERMS OF THE
+
* [http://www.unixpeople.com/HOWTO/configuring.ssh.html unixpeople.com]
    CONSULTING AGREEMENT UNDER WHICH THIS SOFTWARE WAS DEVELOPED.
+
===Use SSH config file===
 +
<pre>
 +
Host server10
 +
  Hostname 1.2.3.4
 +
  IdentityFile ~/.ssh/id_dsa
 +
  user foobar
 +
  Port 30000
 +
  ForwardX11Trusted yes
 +
  TCPKeepAlive yes
 +
</pre>
 +
then just connect using
 +
<pre>
 +
ssh server10
 +
</pre>
  
#!/bin/ksh
+
===A decent sed tutorial===
function handle_signal
+
From [http://www.grymoire.com/Unix/Sed.html grymoire.com]
{
+
===A decent korn/bash shell tutorial===
        print -n "pid $$ recieved $2 "
+
From [http://www.dartmouth.edu/~rc/classes/ksh/print_pages.shtml dartmouth.edu]
        if [[ $1 = 0 ]];then
+
Reproduced here just in case it disappears!
            print but foreground command ended successfully
+
[[Advanced shell scripting]]
        else
+
 
                if [[ $1 = $3 ]];then
+
===trap===
                    print and so did the last foreground command
+
<pre>
                else
+
    Example Handling Traps With ksh - Discussion of the kill command
                    print -n "and the exit status of the last foreground "
+
 
                    print command was $1
+
 
                fi
+
EXAMPLE TEMPLATE:
        fi
+
 
        # Kill our process group and then ourselves with SIGTERM, giving a  
+
 
        # pid of 0 sends the signal to our process group. Killing the process
+
PRODUCT:    HP-UX 11iV1 Version B.11.11
        # group should kill us as well, this assumes that SIGTERM is not
+
            HP Tru64 V5.1B PK4
        # handled by any process in the process group.
+
            Sun/Solaris SunOS V5.8
        #
+
            Linux 2.6 kernel
        # This code could be replaced with an exit with an exit value that
+
 
        # would indicate what the problem was to the caller. That is replace
+
 
        # these two lines with:
+
COMPONENT:  ksh
        #
+
 
        # exit $3
+
 
        #
+
SOURCE:    Philippe Vouters
        # or a specific exit code could be used.
+
            Fontainebleau/France
        #
+
 
        kill -TERM 0
+
 
        kill -TERM $$
+
LOW COST HIGH-TECH PRODUCTS:  http://techno-star.fr
        }
+
 
OS=$(uname -a | awk '{print $1}')
+
 
if [[ "$OS" = "Linux" ]]; then
+
OVERVIEW:
    offset=256
+
 
elif [[ ("$OS" = "HP-UX") ||
+
The ksh script below shows how to eventually handle traps in the situation
        ("$OS" = "SunOS") ||
+
where someone might try to kill a script by killing individual commands run
        ("$OS" = "OSF1") ]]; then
+
by that script or the entire process group a script is running in. The kill
  offset=128
+
command (usually a shell builtin) may be used to send a signal to a process  
fi
+
group (with the -<pid> syntax) or an individual process. The example ksh
trap 'RC=$?; handle_signal $RC SIGINT $offset+2' INT
+
script below runs /bin/sleep as the foreground process, the example ksh
trap 'RC=$?; handle_signal $RC SIGQUIT $offset+3' QUIT
+
scripts immediately returns when the /bin/sleep process has terminated. Most
/bin/sleep 20
+
signals sent to the shell are ignored until after the foreground process
echo $?
+
terminates. This is in order to avoid creating zombie processes. Therefore a
</pre>
+
kill <pid> on the example ksh script waits for the termination of the  
===DNS not working===
+
/bin/sleep process.
Ping to an IP address works
+
 
ping 74.125.136.103
+
The status value $? in the trap refers to the exit status of the command to run
but this doesn't
+
and therefore is the exit status of the /bin/sleep process. The called function
ping www.google.com
+
in the trap handler shows how to correctly examine the effect of the kill  
 +
command on the shell or it's children.
 +
 
 +
To examine the value of $? in a trap handler means that you must understand what
 +
it can be set and how different signals delivered to either the shell or the
 +
foreground process (or the process group) might affect the value of $?.
 +
 
 +
The example shell script prints $? using echo but it does not perform tests on
 +
the value of $?. For a complete solution when attempting to trap signals in a
 +
shell you would also need code that examined the value of $? after the
 +
foreground process had completed.
  
Check resolv.conf
 
cat /etc/resolv.conf
 
nameserver 95.130.132.17
 
nameserver 95.130.132.18
 
I had changed internet provider and forgot to update this. Just to set it to the router address and let that do the resolution
 
nameserver 192.168.1.1
 
  
===File descriptors===
+
*** CAUTION ***
<pre>
+
 
exec 3<> /tmp/foo  #open fd 3 for r/w
+
This sample script has been tested using HP-UX B.11.11, HP Tru64 V5.1B PK4,
echo "test" >&3
+
SunOS V5.8 and Fedora Core 4 (homed version of Red Hat Linux). However, we
exec 3>&- #close fd 3.
+
cannot guarantee its effectiveness because of the possibility of error in
</pre>
+
transmitting or implementing it. It is meant to be used as a template for
<pre>
+
writing your own scripts, and may require modification for use on your system.  
exec 3<> myfile.txt
 
while read line <&3
 
do {
 
  echo "$line"
 
  (( Lines++ ));                  # Incremented values of this variable
 
                                  #+ accessible outside loop.
 
                                  #  No subshell, no problem.
 
}
 
done
 
exec 3>&-
 
  
echo "Number of lines read = $Lines"    # 8
 
</pre>
 
Mmm. See our output and also tee it to a log file!
 
<pre>
 
#!/bin/bash
 
  
echo hello
+
SCRIPT NOTES:
  
if test -t 1; then
+
To notice that the ksh script and /bin/sleep share the same process group
    # Stdout is a terminal.
+
identifier (PGID), issue the following commands:
    exec >log
 
else
 
    # Stdout is not a terminal.
 
    npipe=/tmp/$$.tmp
 
    trap "rm -f $npipe" EXIT
 
    mknod $npipe p
 
    tee <$npipe log &
 
    exec 1>&-
 
    exec 1>$npipe
 
fi
 
  
echo goodbye
+
[philippe@victor ~]$ who
</pre>
+
philippe :0          Jan 10 10:16
 +
philippe pts/1        Jan 10 21:30 (:0.0)
 +
philippe pts/2        Jan 10 21:30 (:0.0)
 +
[philippe@victor ~]$ tty
 +
/dev/pts/1
 +
[philippe@victor ~]$ ps -j -t pts/2
 +
  PID  PGID  SID TTY          TIME CMD
 +
11072 11072 11072 pts/2    00:00:00 bash
 +
11113 11113 11072 pts/2    00:00:00 ksh
 +
11116 11113 11072 pts/2    00:00:00 sleep
  
===Create new image with kvm===
+
In this case sending kill -INT -11113 will send SIGINT to the process group
Ref: http://www.cyberciti.biz/faq/kvm-virtualization-in-redhat-centos-scientific-linux-6/<br />
+
11113. Both of the ksh and sleep processes are contained within this process
Build an empty space for a CentOS virtual machine
+
group.
<pre>
+
 
qemu-img create -f qcow2 centos.img 12G
+
Important Note:
</pre>
 
Tried creating image with
 
<pre>
 
sudo virt-install -n CentOS --description "Trying out CentOS" --ram=1024 --vcpus=1 --cpu host --hvm --cdrom /home/bey9at77/Downloads/c6-x86_64-20130910-1.qcow2 --graphics vnc --disk path=/var/lib/libvirt/images/centos.img,bus=virtio,size=10
 
</pre>
 
gives error
 
<pre>
 
Starting install...
 
Allocating 'centos.img'                                                                                                                                                                                              |  10 GB    00:00   
 
ERROR    internal error Process exited while reading console log output: char device redirected to /dev/pts/1
 
qemu-kvm: -drive file=/home/bey9at77/Downloads/c6-x86_64-20130910-1.qcow2.bz2,if=none,media=cdrom,id=drive-ide0-1-0,readonly=on,format=raw: could not open disk image /home/bey9at77/Downloads/c6-x86_64-20130910-1.qcow2: Permission denied
 
</pre>
 
<pre>
 
</pre>
 
<pre>
 
</pre>
 
  
===Install rpmforge repository===
+
On HP-UX, you have to $ export UNIX95=1 in order to be able to use the
* Download rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
+
-j option of the ps command.
* Import the key
+
 
<pre>
+
 
sudo rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt
+
SCRIPT:
</pre>
+
 
* Install the repository
+
                            COPYRIGHT (C) 2005 BY
<pre>
+
                              HEWLETT-PACKARD COMPANY
sudo rpm -i rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
+
                                ALL RIGHTS RESERVED.
</pre>
+
 
* Check the installation
+
    THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
<pre>
+
    ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE INCLUSION
rpm -K rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
+
    OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY OTHER COPIES
</pre>
+
    THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER
* Test it
+
    PERSON.  NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
<pre>
+
 
sudo yum install terminator
+
    THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
</pre>
+
    SHOULD NOT BE CONSTRUED AS A COMMITMENT BY HEWLETT-PACKARD COMPANY.
===Install rpmfusion repository===
+
 
<pre>
+
    HP ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
su -c 'yum localinstall --nogpgcheck http://download1.rpmfusion.org/free/el/updates/6/i386/rpmfusion-free-release-6-1.noarch.rpm http://download1.rpmfusion.org/nonfree/el/updates/6/i386/rpmfusion-nonfree-release-6-1.noarch.rpm'
+
    SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY HP.
 +
 
 +
    NO RESPONSIBILITY IS ASSUMED FOR THE USE OR RELIABILITY OF SOFTWARE
 +
    ON EQUIPMENT THAT IS NOT SUPPLIED BY HEWLETT-PACKARD COMPANY.
 +
 
 +
    SUPPORT FOR THIS SOFTWARE IS NOT COVERED UNDER ANY HP SOFTWARE
 +
    PRODUCT SUPPORT CONTRACT, BUT MAY BE PROVIDED UNDER THE TERMS OF THE
 +
    CONSULTING AGREEMENT UNDER WHICH THIS SOFTWARE WAS DEVELOPED.
 +
 
 +
#!/bin/ksh
 +
function handle_signal
 +
{
 +
        print -n "pid $$ recieved $2 "
 +
        if [[ $1 = 0 ]];then
 +
            print but foreground command ended successfully
 +
        else
 +
                if [[ $1 = $3 ]];then
 +
                    print and so did the last foreground command
 +
                else
 +
                    print -n "and the exit status of the last foreground "
 +
                    print command was $1
 +
                fi
 +
        fi
 +
        # Kill our process group and then ourselves with SIGTERM, giving a
 +
        # pid of 0 sends the signal to our process group. Killing the process
 +
        # group should kill us as well, this assumes that SIGTERM is not
 +
        # handled by any process in the process group.
 +
        #
 +
        # This code could be replaced with an exit with an exit value that
 +
        # would indicate what the problem was to the caller. That is replace
 +
        # these two lines with:
 +
        #
 +
        # exit $3
 +
        #
 +
        # or a specific exit code could be used.
 +
        #
 +
        kill -TERM 0
 +
        kill -TERM $$
 +
        }
 +
OS=$(uname -a | awk '{print $1}')
 +
if [[ "$OS" = "Linux" ]]; then
 +
    offset=256
 +
elif [[ ("$OS" = "HP-UX") ||
 +
        ("$OS" = "SunOS") ||
 +
        ("$OS" = "OSF1") ]]; then
 +
  offset=128
 +
fi
 +
trap 'RC=$?; handle_signal $RC SIGINT $offset+2' INT
 +
trap 'RC=$?; handle_signal $RC SIGQUIT $offset+3' QUIT
 +
/bin/sleep 20
 +
echo $?
 +
</pre>
 +
===DNS not working===
 +
Ping to an IP address works
 +
ping 74.125.136.103
 +
but this doesn't
 +
ping www.google.com
 +
 
 +
Check resolv.conf
 +
cat /etc/resolv.conf
 +
nameserver 95.130.132.17
 +
nameserver 95.130.132.18
 +
I had changed internet provider and forgot to update this. Just to set it to the router address and let that do the resolution
 +
nameserver 192.168.1.1
 +
 
 +
===File descriptors===
 +
<pre>
 +
exec 3<> /tmp/foo  #open fd 3 for r/w
 +
echo "test" >&3
 +
exec 3>&- #close fd 3.
 +
</pre>
 +
<pre>
 +
exec 3<> myfile.txt
 +
while read line <&3
 +
do {
 +
  echo "$line"
 +
  (( Lines++ ));                  #  Incremented values of this variable
 +
                                  #+ accessible outside loop.
 +
                                  #  No subshell, no problem.
 +
}
 +
done
 +
exec 3>&-
 +
 
 +
echo "Number of lines read = $Lines"    # 8
 +
</pre>
 +
Mmm. See our output and also tee it to a log file!
 +
<pre>
 +
#!/bin/bash
 +
 
 +
echo hello
 +
 
 +
if test -t 1; then
 +
    # Stdout is a terminal.
 +
    exec >log
 +
else
 +
    # Stdout is not a terminal.
 +
    npipe=/tmp/$$.tmp
 +
    trap "rm -f $npipe" EXIT
 +
    mknod $npipe p
 +
    tee <$npipe log &
 +
    exec 1>&-
 +
    exec 1>$npipe
 +
fi
 +
 
 +
echo goodbye
 +
</pre>
 +
 
 +
===Create new image with kvm===
 +
Ref: http://www.cyberciti.biz/faq/kvm-virtualization-in-redhat-centos-scientific-linux-6/<br />
 +
Build an empty space for a CentOS virtual machine
 +
<pre>
 +
qemu-img create -f qcow2 centos.img 12G
 +
</pre>
 +
Tried creating image with
 +
<pre>
 +
sudo virt-install -n CentOS --description "Trying out CentOS" --ram=1024 --vcpus=1 --cpu host --hvm --cdrom /home/bey9at77/Downloads/c6-x86_64-20130910-1.qcow2 --graphics vnc --disk path=/var/lib/libvirt/images/centos.img,bus=virtio,size=10
 +
</pre>
 +
gives error
 +
<pre>
 +
Starting install...
 +
Allocating 'centos.img'                                                                                                                                                                                              |  10 GB    00:00   
 +
ERROR    internal error Process exited while reading console log output: char device redirected to /dev/pts/1
 +
qemu-kvm: -drive file=/home/bey9at77/Downloads/c6-x86_64-20130910-1.qcow2.bz2,if=none,media=cdrom,id=drive-ide0-1-0,readonly=on,format=raw: could not open disk image /home/bey9at77/Downloads/c6-x86_64-20130910-1.qcow2: Permission denied
 +
</pre>
 +
===rpm / yum commands===
 +
====Install an RPM Package====
 +
<pre>
 +
rpm -ivh pidgin-2.7.9-5.el6.2.i686.rpm
 +
 
 +
-i - install
 +
-v - verbose
 +
-h - print progress hashes
 +
</pre>
 +
 
 +
====Check dependencies of RPM Package before Installing====
 +
<pre>
 +
rpm -qpR BitTorrent-5.2.2-1-Python2.4.noarch.rpm
 +
 
 +
-q - query
 +
-p - list package capabilities
 +
-R - list dependent package capabilities
 +
</pre>
 +
 
 +
====Install RPM Package with all dependencies====
 +
<pre>
 +
yum install BitTorrent-5.2.2-1-Python2.4.noarch.rpm
 +
</pre>
 +
====Install RPM Package with all dependencies (when RPM has been downloaded to local machine)====
 +
<pre>
 +
yum localinstall BitTorrent-5.2.2-1-Python2.4.noarch.rpm
 +
</pre>
 +
====Force Install a RPM Package without dependencies====
 +
Package will not work if dependencies are required
 +
<pre>
 +
rpm -ivh --nodeps BitTorrent-5.2.2-1-Python2.4.noarch.rpm
 +
</pre>
 +
====Check an Installed RPM Package====
 +
<pre>
 +
rpm -q BitTorrent
 +
</pre>
 +
====List all files of an installed RPM package====
 +
<pre>
 +
rpm -ql BitTorrent
 +
</pre>
 +
====List All Installed RPM Packages====
 +
<pre>
 +
rpm -qa
 +
</pre>
 +
====Query information about an installed RPM package====
 +
<pre>
 +
rpm -qi vsftpd
 +
</pre>
 +
====Query information about a not yet installed RPM package====
 +
<pre>
 +
rpm -qip sqlbuddy-1.3.3-1.noarch.rpm
 +
</pre>
 +
====(Forcibly) Remove an RPM Package====
 +
Use package name (as seen in -qi above), not full name
 +
<pre>
 +
rpm -ev (--nodeps) vsftpd
 +
</pre>
 +
====Query a file that was installed as part of an RPM Package (which package contained this file)====
 +
<pre>
 +
rpm -qf /usr/bin/htpasswd
 +
</pre>
 +
====Verify an RPM package====
 +
Compares information of installed files of the package against the rpm database
 +
<pre>
 +
rpm -Vp sqlbuddy-1.3.3-1.noarch.rpm
 +
</pre>
 +
====Rebuild corrupted RPM database====
 +
<pre>
 +
cd /var/lib
 +
rm __db*
 +
rpm --rebuilddb
 +
rpmdb_verify Packages
 +
</pre>
 +
 
 +
===Install rpmforge repository===
 +
* Download rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
 +
* Import the key
 +
<pre>
 +
sudo rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt
 +
</pre>
 +
* Install the repository
 +
<pre>
 +
sudo rpm -i rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
 +
</pre>
 +
* Check the installation
 +
<pre>
 +
rpm -K rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
 +
</pre>
 +
* Test it
 +
<pre>
 +
sudo yum install terminator
 +
</pre>
 +
===Install rpmfusion repository===
 +
<pre>
 +
su -c 'yum localinstall --nogpgcheck http://download1.rpmfusion.org/free/el/updates/6/i386/rpmfusion-free-release-6-1.noarch.rpm http://download1.rpmfusion.org/nonfree/el/updates/6/i386/rpmfusion-nonfree-release-6-1.noarch.rpm'
 +
</pre>
 +
 
 +
===config file for yum===
 +
Checkout this file for global yum config
 +
<pre>
 +
/etc/sysconfig/yum-cron-background
 +
</pre>
 +
 
 +
===Setup Oracle Enterprise Linux (RedHat) with yum server===
 +
You need to download the yum .repo file from the server, as per the steps below. After this, you need to enable a flag in the .repo file as per your operating system version. Having done these two steps, when you run yum install <pkgname> command on your linux box, the Oracle's yum server will be scanned, the dependent & the relevant rpm's will be download and installed for you.<br />
 +
cd /etc/yum.repos.d
 +
To download files here
 +
wget http://public-yum.oracle.com/public-yum-el5.repo
 +
 
 +
A file named public-yum-el5.repo will be created in your directory<br />
 +
Edit this file and enter enabled=1 against the operating systems which is relevant to you
 +
vi public-yum-el5.repo
 +
 
 +
Next run the yum command
 +
yum install package-name
 +
 
 +
===To change to static IP address (Raspberry Pi)===
 +
As root:
 +
<pre>
 +
cd /etc/networks
 +
vi interfaces
 +
</pre>
 +
 
 +
replace the line “iface eth0 inet dhcp” with
 +
<pre>
 +
iface eth0 inet static
 +
address 192.168.1.100
 +
netmask 255.255.255.0
 +
gateway 192.168.1.1
 
</pre>
 
</pre>
  
===config file for yum===
+
You should also take a look at the file /etc/resolv.conf and check it has a nameserver entry (probably pointing at your default gateway) or direct to your ISP name servers.
Checkout this file for global yum config
 
 
<pre>
 
<pre>
/etc/sysconfig/yum-cron-background
+
nameserver 192.168.1.1
 
</pre>
 
</pre>
 
+
===Troubleshoot wireless network problems===
===Setup Oracle Enterprise Linux (RedHat) with yum server===
+
* [https://www.blackmoreops.com/2014/09/18/connect-to-wifi-network-from-command-line-in-linux/ connect to wifi network from command-line in linux - from blackmoreops.com]
You need to download the yum .repo file from the server, as per the steps below. After this, you need to enable a flag in the .repo file as per your operating system version. Having done these two steps, when you run yum install <pkgname> command on your linux box, the Oracle's yum server will be scanned, the dependent & the relevant rpm's will be download and installed for you.<br />
+
'''Short summary of all the things you need to do in just few lines'''
cd /etc/yum.repos.d
 
To download files here
 
wget http://public-yum.oracle.com/public-yum-el5.repo
 
 
 
A file named public-yum-el5.repo will be created in your directory<br />
 
Edit this file and enter enabled=1 against the operating systems which is relevant to you
 
vi public-yum-el5.repo
 
 
 
Next run the yum command
 
yum install package-name
 
 
 
===To change to static IP address (Raspberry Pi)===
 
As root:
 
<pre>
 
cd /etc/networks
 
vi interfaces
 
</pre>
 
 
 
replace the line “iface eth0 inet dhcp” with
 
 
<pre>
 
<pre>
iface eth0 inet static
 
address 192.168.1.100
 
netmask 255.255.255.0
 
gateway 192.168.1.1
 
</pre>
 
 
You should also take a look at the file /etc/resolv.conf and check it has a nameserver entry (probably pointing at your default gateway) or direct to your ISP name servers.
 
<pre>
 
nameserver 192.168.1.1
 
</pre>
 
===Troubleshoot wireless network problems===
 
* [https://www.blackmoreops.com/2014/09/18/connect-to-wifi-network-from-command-line-in-linux/ connect to wifi network from command-line in linux - from blackmoreops.com]
 
<pre>
 
'''Short summary of all the things you need to do in just few lines'''
 
 
 
root@kali:~# iw dev
 
root@kali:~# iw dev
 
root@kali:~# ip link set wlan0 up
 
root@kali:~# ip link set wlan0 up

Latest revision as of 00:18, 6 December 2018

Contents

How to automatically download and process email attachments from Gmail[edit]

Useful references[edit]

Eventually, after months of trying different things, came up with this combination of tools that worked very well.

Install tools[edit]

sudo dnf -y install fetchmail maildrop uudeview openssl
  • Set Gmail account up for POP and disable IMAP

Configure fetchmail[edit]

This is the part that talks to Gmail and downloads the emails to the local machine.

vi ~/.fetchmailrc

set postmaster "<username>"
#set daemon 600
poll pop.gmail.com with proto POP3
    user "[email protected]" there with password '<password>' is <username> here options ssl nokeep
    mda "/usr/bin/maildrop .mailfilter"
#    sslcertfile /etc/ssl/certs/ca-bundle.crt

If fetchmail complains about ssl certificates, try specifying wherein is with the sslcertfile line

Configure maildrop[edit]

maildirmake maildrop
maildirmake backup

vi ~/.mailfilter

LOGFILE = "/home/dbahawk/maildrop/maildrop.log"
DEFAULT="$HOME/maildrop"

# keep a copy
cc backup
`cd backup/new && rm -f dummy \`ls -t | sed -e 1,50d\``

if (/^To:.*getmail@...\.dnsalias\.org$/)
   {
        to Maildir/getmail/
   }

#if (/^To:.*dbahawk/)
#   {
#        to maildrop
#   }

if (/^To:.*dbahawk/)
    dotlock "auto.lock" {
    to "|uudeview -c -i"
}

Not really sure why this filter is not working properly. The cc works but the To: check doesn't. So I have a shell that runs separately to process the emails in the backup mail directory.

uudeview[edit]

This is a clever program that can extract attachments from emails and put them in a directory of you choosing.
This shell runs from cron at regular intervals to run the whole process

#!/usr/bin/ksh

# fetch any new mail from Gmail (uses .fetchmailrc)
# fetchmail log is $HOME/maildrop/maildrop.log
fetchmail -d0

# fetchmail uses maildrop as mda (uses .mailfilter) to save messages to a maildir.
# this is not working correctly but still copies the messages to backup

# pull out the attachments and send them to the incoming directory for the collector to process when it wakes up
uudeview -c -i -p ~/Downloads/dbahawk_forward backup/new/*

Use sed to repeat characters[edit]

echo an '=' sign then use the loop feature of sed to run round a loop a further 79 times replacing what you've got with the same thing plus and extra one!

echo "=" | sed -e :a -e 's/^=\{1,79\}$/&=/;ta'

Convert between lower and upper case using ansi standard[edit]

This way should be portable and give predictable results

LOWER_SID=$(echo "${SID}" | tr '[:upper:]' '[:lower:]')
UPPER_SID=$(echo "${SID}" | tr '[:lower:]' '[:upper:]')

Use sed to delete the first line of a file or command output printing from the second line onwards[edit]

Actually deceptively simple. Example remove the header from df output.

df -k | sed 1d

or more formally

df -k | sed -e '1,1d'

As a useful extension, suppose TO_DATA_DIR contains multiple directories, this will total the free space for all relevant filesystems
This one is specific to AIX, for other Unixes and Linux, use $4 instead of $3.

SPACE_AVAILABLE=$(df -k $TO_DATA_DIR | sed 1d | awk 'BEGIN {i=0} {i=i+$3} END {print i}')

Use sed to munge a controlfile into submission![edit]

  • delete comment lines
  • delete all lines after the one starting with a semicolon
  • delete all blank lines
  • change reuse to set
  • change archivelog (with word boundaries) to noarchivelog
  • change old sid to new sid
sqlplus -s / as sysdba<<'EOSQL' >/dev/null
alter database backup controlfile to trace as '/tmp/regenerate_controlfile.sql' reuse resetlogs;
EOSQL
OLDSID='PROD'
NEWSID='TEST'
sed  -e '/^--/d' -e '/^\;/q' -e '/^ *$/d' -e 's/REUSE/SET/' -e 's/\<ARCHIVELOG\>/NOARCHIVELOG/' -e 's/\"'${OLDSID}'\"/\"'${NEWSID}'\"/' /tmp/regenerate_controlfile.sql

Find all files where a certain text does not exist[edit]

Mostly we want to search for files containing a particular string but how to find those files that do not contain some text.
Using xargs instead of -exec forces the filename to be printed. -H should do this but doesn't seem to in this case.

find . -name "*cfg" | xargs grep -H -c TO_CV_HOST {} \; | grep ':0$' | cut -d: -f1

Use tar and gzip to copy files more efficiently across network between hosts[edit]

From the destination server, this will connect to the source, tar up each file and pull it back to the current server

ssh oracle@hn5211 "cd /oracle/ora_data4/iten3/ && tar -cf - . | gzip " | ( cd /oracle/ora_data2/iten/ && gunzip -c | tar -xvf - . )

double hash and double percent in shell variables to trim off characters from variables[edit]

# - trims everything from the start of line till the FIRST occurrence of following character (abstemious) :-)
## - trims everything from the start of line till the LAST occurrence of following character (greedy)
% - trims everything from the end of line backwards till the FIRST occurrence of following character (abstemious)
%% - trims everything from the end of line backwards till the LAST occurrence of following character (greedy)

FILENAME="/home/bey9at77/hello.txt"
FILE_STUB1=${FILENAME##*/}
FILE_STUB=${FILE_STUB1%.*}
echo $FILE_STUB
hello
FILE_EXT=${FILENAME##*.}
echo $FILE_EXT
txt

or
# - remove prefix reluctantly
## - remove prefix greedily
% - remove suffix reluctantly
%% - remove suffix greedily

words="do.re.mi"

echo ${words#*.}

echo ${words##*.}

echo ${words%.*}

echo ${words%%.*}

The best shell script ever. An example of how scripting should be done[edit]

It was written by someone at Oracle. Unfortunately (s)he did not put any author comment in it. Also unfortunately I cannot show it here as it is protected behind Oracles support website.
If you have an Oracle Metalink id, you can get the complete script here
Here is a snippet of a function that demonstrates proper commenting and a very good style.
The script is called physru.sh and upgrades an Oracle database in a rolling upgrade fashion by using a physical standby.
There are 4500 lines in the full script but it is so easy to read and understand because of the way it's written, it's like a breath of fresh air. Well done whoever you are!

###############################################################################
# NAME:        wait_mrp_active
#
# DESCRIPTION: 
#   Wait for $MRP_START_TIMEOUT minutes to confirm that the MRP is active.  If
#   we can't detect an active MRP, abort the script with an error.
#
# INPUT(S):
#   Arguments:
#     $1: database user
#     $2: user password
#     $3: tns service name
#     $4: database unique name
#
#   Globals:
#     None
#
# RETURN:
#   None
#
###############################################################################
wait_mrp_active()
{
  display "confirming media recovery is running"
  l_wma_status=1
  l_wma_curtime=`perl -e 'print int(time)'`
  l_wma_exptime=`expr $MRP_START_TIMEOUT "*" 60`
  l_wma_maxtime=`expr $l_wma_curtime + $l_wma_exptime`
  while [ "$l_wma_curtime" -lt "$l_wma_maxtime" ]
  do
    is_mrp_running $1 $2 $3 $4
    if [ "$?" -gt "0" ]; then
      l_wma_status=0
      break
    fi

    sleep $MRP_START_INTERVAL
    l_wma_curtime=`perl -e 'print int(time)'`
  done
  chkerr $l_wma_status "could not detect an active MRP after $MRP_START_TIMEOUT minutes"
}

split variable (eg. filename) into separate variables using set[edit]

FILENAME="split_this_into_bits"
set $(echo ${FILENAME} | sed 's/_/ /g')
echo $4 $3 $2 $1
bits into this split

Centre align text on a line in bash shell[edit]

Doesn't work in Korn shell due to %*s

#COLUMNS=$(tput cols)   # width of the current window
COLUMNS=80
title="Hello world!"
printf "%*s\n" $(((${#title}+$COLUMNS)/2)) "$title"

and as a one-liner

printf "%*s\n" $(( ( $(echo $* | wc -c ) + 80 ) / 2 )) "$*"

This works in Korn shell...

TITLE="$1"
LINEWIDTH=80

LPAD=$(((${#TITLE}+$LINEWIDTH)/2))
printf %${LPAD}s "$TITLE"

Right justify text (or repeat characters) on a line with leader dots![edit]

function rpadwait {
    text=$1
# -------------------------
# suppress newline for echo
# -------------------------
N=
C=
if echo "\c" | grep c >/dev/null 2>&1; then
    N='-n'
else
    C='\c'
fi


    echo ${N} "${text}${C}" | sed -e :a -e 's/^.\{1,80\}$/&\./;ta'
}

cron jobs not submitted - daemon run out of child processes?[edit]

Sometimes have problems with NFS mounts and this causes cron jobs to hang. If they are scheduled to run regularly, eventually cron will no longer be able to start any more jobs.

  • Check the cron log /var/adm/cron/log to see if there are any errors or other messages around the time the jobs should run.

If cron has hit its process limit (default 100), it will try again after a number of seconds (default 60).
Both the number of jobs and wait time are configured in the file /var/adm/cron/queuedefs. If it is unusual for cron to be running so many jobs, you can check the process table to view the jobs cron has created. These jobs will have parent process id (PPID) of the cron daemon.

$ ps -ef | grep cron | grep -v grep
    root  6750314        1   0   Apr 24      -  3:39 /usr/sbin/cron
solax025:root[/home/root]# ps -T 6750314
      PID    TTY  TIME CMD
  6750314      -  3:39 cron
 21168296      -  0:00     \--bsh
 58982414      -  0:00         \--sadc

In this example, we only have 1 job running

Find long-running processes with a cron job[edit]

Processes running longer than 24 hours have a date instead of a start time...

58 08,14 * * * /home/ibmtools/scripts/oracle/dosh -vc "ps -ef|grep 'ibmtools/scripts/oracle'|perl -nae 'print if \$F[4] !~/:/'" >/tmp/lrp.txt; [[ $(grep -c ibmtools /tmp/lrp.txt) -ne 0 ]] && cat /tmp/lrp.txt|mailx -s '*** long running processes - please check ***' [email protected]

Process command line arguments in shell[edit]

Borrowed from Mozilla Firefox installer

## Command line arg defaults
##
moz_debug=0
moz_debugger=""
moz_debugger_args=""
#
##
## Parse the command line
##
while [ $# -gt 0 ]
do
  case $1 in
    -g | --debug)
      moz_debug=1
      shift
      ;;
    -d | --debugger)
      moz_debugger=$2;
      if [ "${moz_debugger}" != "" ]; then
	shift 2
      else
        echo "-d requires an argument"
        exit 1
      fi
      ;;
    -a | --debugger-args)
      moz_debugger_args=$2;
      if [ "${moz_debugger_args}" != "" ]; then
	shift 2
      else
        echo "-a requires an argument"
        exit 1
      fi
      ;;
    *)
      break;
      ;;
  esac
done
#
##
## Program name given in $1
##
if [ $# -gt 0 ]
then
	MOZ_PROGRAM=$1
	shift
fi
##
## Program not given, try to guess a default
##
if [ -z "$MOZ_PROGRAM" ]
then
	##
	## Try this script's name with '-bin' appended
	##
	if [ -x "$MOZ_DEFAULT_NAME" ]
	then
		MOZ_PROGRAM=$MOZ_DEFAULT_NAME
	##
	## Try mozilla-bin
	## 
	elif [ -x "$MOZ_APPRUNNER_NAME" ]
	then
		MOZ_PROGRAM=$MOZ_APPRUNNER_NAME
	fi
fi
#
#
##
## Make sure the program is executable
##
if [ ! -x "$MOZ_PROGRAM" ]
then
	moz_bail "Cannot execute $MOZ_PROGRAM."
fi
#

Carry XWindows settings across sessions[edit]

# ----------------------
# push XWindows settings
# ----------------------
[[ "$(uname)" == "SunOS" ]] && PATH=/usr/openwin/bin:$PATH
WHOAMI=$(id | awk -F')' '{print $1}' | awk -F'(' '{print $2}')
xauth list > /tmp/xauth_list_$WHOAMI
chmod 777 /tmp/xauth_list_$WHOAMI

echo $DISPLAY > /tmp/xdisplay_$WHOAMI
chmod 777 /tmp/xdisplay_$WHOAMI

Cross-platform version of whoami[edit]

WHOAMI=$(id | awk -F')' '{print $1}' | awk -F'(' '{print $2}')

Set terminal title from command line[edit]

Put something like this in the .profile
-n do not output the trailing newline
-e enable interpretation of backslash escapes
|0 sets title of window and icon
|1 sets title of icon only
|2 sets title of window only

echo -en "\033]0;`hostname`\007"
echo -en "\033]2;`hostname`\007"

Remove blank lines and comments (also indented ones) from a file[edit]

awk -F\: '!/^($|[:space:]*#)/ {print $2}' /etc/oratab | sort | uniq

or as part of a script that removes comments and blank lines from all Korn shell scripts in a directory

#!/usr/bin/ksh
for i in $(ls *ksh); do
    perl -p -i -e 's/^\s*#[^!]*$//; s/^\s*$//' $i
done

Return elements of an array in Korn shell[edit]

From here
Could be used to separate the columns of an SQL select when returning to the shell
This approach eliminates the need to put quotes around text with spaces in it.

echo $KSH_VERSION
x="Red,Yellow is a color,Blue"
oIFS=$IFS
IFS=,
y=($x)
IFS=$oIFS
echo ${y[1]}

A decent Unix Prompt[edit]

export PS1="`uname -n`:`whoami`[\${PWD}]# "
or
export PS1='($?) $'ORACLE_SID" "`whoami`"@"`uname -n`":"'$'PWD"> "
export EDITOR=vi

Simple arithmetic[edit]

pipe the calculation into the shell calculator

space_in_kb=$(echo $1 / 1024 | bc)

Calculate the remainder (modulo) of a division calculation

if [[ $(echo "${NUMBER} % 2" | bc) -eq 0 ]]; then
    echo "${NUMBER} is even"
else
    echo "${NUMBER} is odd"
fi

or do it in awk if scientific notation maybe involved

function calc { awk "BEGIN{print $*}"; }

if [[ $(calc "${SPACE_USED} + ${SPACE_AVAILABLE} - ${DATABASE_SIZE") -le 0 ]]; then
    echo "NOK"
fi

Script encryption and passphrase protection[edit]

Encrypt a shell script with the ability to execute the encrypted version

scrypt(){ [ -n "$1" ]&&{ echo '. <(echo "$(tail -n+2 $0|base64 -d|mcrypt -dq)"); exit;'>$1.scrypt;cat $1|mcrypt|base64 >>$1.scrypt;chmod +x $1.scrypt;};}

Virtual host configuration in Apache http.conf[edit]

<VirtualHost *:80>
        ServerName dbamon
        DocumentRoot "/Volumes/data/Sites/dbamon_push"
        <Directory "/Volumes/data/Sites/dbamon_push">
                Options Includes FollowSymLinks
                AllowOverride All
                Order allow,deny
                Allow from all
        </Directory>
</VirtualHost>

and in /etc/hosts, add...

127.0.0.1  dbamon

Mount a website (or any other remote resource) locally using WebDav[edit]

Redhat/CentOS

yum install fuse-davfs2
or
yum install wdfs.x86_64

Debian

apt-get install davfs2

then...

sudo mkdir /mnt/webdav  # or whatever you'd like to call the directory
sudo mount.davfs [-o option[,option]...] device mount_point

In man's terms, that last line would translate to:

id  #suppose this returns uid=501 and gid=502
sudo mount.davfs -o 501,502 https://your/web/site /mnt/webdav

Mac OSX

osascript -e ' mount volume "http://username:[email protected]:portnum" '
or
osascript -e ' mount volume "http://[email protected]:portnum" '
or
osascript -e ' try mount volume "http://webdav.address:portnum" '
or
mount -t webdav http://webdav.address:portnum /mnt/webdav  # this one won't show up in the Finder Sidebar.

Add current hostname to list of hosts on an xcat server[edit]

CMD="nodels"
HOST=`hostname`
(echo "$HOST"; $CMD) | while read server
do
    echo "server:$server"
done

What is todays 'Day Of the Year' number?[edit]

DOY=`perl -e 'print sub{$_[7]}->(localtime)+1;'`

Convert Julian day numbers to dates[edit]

for day in 8 33 36 61 64 91 96 121 126 152 155 182 187 215 218 244 247 274 279 306 309 335 338 365; do date -d "`date +%Y`-01-01 +$(( ${day} - 1 ))days" +%d-%m-%Y; done

Send crontab job output to a date formatted log file[edit]

This will run a job every 5 minutes and send the output to a file ending with a time in hours and minutes.
The thing to note is the escaped percent signs. This is because a % sign is interpreted by cron to mean a newline character. Everything after the first % is treated as input to the program.

*/5 *  * * * /var/www/cgi-bin/dbamon_collector.ksh       >/tmp/dbamon_collector.log.$(date "+\%H\%M") 2>&1

Edit crontab file without crontab -e[edit]

It can happen that you need to add or modify a line in the crontab of many users or across many servers at once.
In principle, there's nothing wrong with modifying the crontab file directly. You just lose the advantages of file locking (and syntax checking) that crontab -e offers.
Here we take a backup of the current crontab, print it out, echo an extra command and ask cron to use these as input (thus overwriting the existing crontab file). Just don't run this close to midnight :-)

crontab -l > /tmp/crontab.`date '+%Y%m%d'`
(
cat /tmp/crontab.`date +'%Y%m%d'`
echo "02 10 * * * /home/ibmtools/scripts/oracle/export_parfile.ksh -s SID -f JDBEOP1.parfile"
) | crontab -

or

crontab -l > /tmp/crontab.backup
crontab -l > /tmp/crontab.$$
perl -p -i -e 's!backup_send_tsm_dump!backup_export2tsm!g' /tmp/crontab.$$
crontab /tmp/crontab.$$
rm /tmp/crontab.$$

or

crontab -l >$HOME/crontab.$(date '+%Y%m%d')
crontab -l | perl -p -e 's|/nas/software/oracle/scripts|/oracle/scripts|' | crontab

Use shell to convert a number in scientific notation to normal[edit]

var2convert='1.2345678e3'
printf -v var2convert "%.f" $var2convert
echo $var2convert  # magic!

Check for jobs running longer that 24 hours[edit]

Run from the management server across all Unix servers. Checks the 5th column in a ps listing. If it doesn't find a : (time separator), the process is running longer than 24 hours.

# ---------------------------------------
# report on long running oraibm processes
# ---------------------------------------
01 17,14 * * * rm -f /tmp/lrp.txt;/home/ibmtools/scripts/oracle/dosh -vc \"ps -ef|egrep 'oraibm|scripts/oracle'>/tmp/lrp.txt;perl -nae 'print if \$F[4] !~/:/' /tmp/lrp.txt\" >>/tmp/lrp.txt;[[ $(egrep -c 'oraibm|scripts/or
acle' /tmp/lrp.txt) -ne 0 ]] && cat /tmp/lrp.txt|mailx -s '*** long running processes - please check ***' [email protected]

Global find and replace with perl (restricted to list of files provided by Unix find command)[edit]

find . -type f -exec perl -i -pe 's/something/else/g' {} \;

perl function to make filenames lower case[edit]

function lower { 
   perl -e 'for (@ARGV) { rename $_, lc($_) unless -e lc($_); }' * 
}

From the management server, search the TNS listener port for each database on a server and make an inline substitution in the ITM config files![edit]

for i in `/home/ibmtools/scripts/oracle/dosh -c "ls -al /opt/IBM/ITM/config/*rz*cfg|grep -v lrwx"|awk '{print $NF}'`; do
    server=`echo $i|cut -d_ -f1 | awk -F'/' '{print $NF}'`
    db=`echo $i|cut -d'.' -f1 | awk -F'_' '{print $NF}'`
    OH=`ssh $server grep "^$db" /etc/oratab|cut -d: -f2`
    LISTENERPORT=`ssh $server cat $OH/network/admin/listener.ora|perl -00 -ne 'print $1 if /'$db'.*PORT.*=.*(\d{4})/s'`
    ssh $server perl -p -i.bak -e 's/1521/'$LISTENERPORT'/' $i
    ssh $server ls -al ${i}*
done

Run a job from cron every Nth day of the month[edit]

Example. Execute a job every third Saturday of the month.
Paste this into a file called calenday and put it in /usr/local/bin so it's (probably) on the PATH

#!/usr/bin/ksh

# ix is the week number of the month ("2"nd Friday of the month, "3"rd Tuesday of the month)
# dy is the day number in Unix format (0 for Sunday, 1 for Monday, ... 6 for Saturday)
# eg. "calenday 3 6" returns the date of 3rd Saturday of the month.

ix=$1
dy=$2
SCHAR=$((($dy*2)+$dy+1))
ECHAR=$(($SCHAR+1))
cal `date '+%m %Y'` | egrep "\<[0-9]{1,2}\>" | cut -c${SCHAR}-${ECHAR} | xargs | awk {'print $'$ix'}'

Now in crontab, you should be able to do something like this:

15 20 * * * [[ `calenday 3 6` -eq `/bin/date '+%d'` ]] && su - oracle -c "run_my_backup.ksh"

This will also work on some Unices..
We send backups to a special TSM node on the second Friday of each month. This report must run a day later - but that is not guaranteed to be the second Saturday or even the 3rd. So...

30 12 8-14 * 5 sleep 86400 && su - oracle -c "/usr/bin/perl -ne 'print if /ORX_M_SOL/ .. /^STOP/' /home/oracle/incoming/dbamon_spool_tsm_*.SOL | grep Archive | grep -v Client | mailx -s 'Monthly TSM backups' [email protected]"

ps listing does not show start time after 24 hours[edit]

But you can see elapsed time using your own ps command

/usr/bin/ps -eo etime,user,pid,ppid,cpu,start,tty,time,args|tail -n +2|sort

ps -ef cuts off args cmd column on Solaris[edit]

To see more than 80 characters of the last column on Solaris[edit]

This shows all the individual arguments to the command

pargs <pid>

This shows the ps listing in 'compatibility' mode (there are more compatibility commands in /usr/xpg4/bin)

/usr/ucb/ps auww

To see more than 80 characters of the last column on AIX[edit]

This shows the full argument listing of a process (NOTE: no minus sign!)

ps eww <pid>

Remove blank / empty lines from vi[edit]

Maybe you cut and pasted a file from Windows and it's full of blank lines and Control-M's now
There are several methods but I think this is the easiest to remember

:g/^$/d

Right pad a variable[edit]

a function like rpad in SQL but for Shell

function rpad {
text=$1
padwidth=$2
padchar=$3
echo "$text" | sed -e :a -e 's/^.\{1,'$padwidth'\}$/&\'$padchar'/;ta'
}

Connect to a Windows server from Linux using rdesktop[edit]

My remmina stopped working so rolled my own. Very simple really. Put this is a shell.

tsocks rdesktop -z -P -x m -a 16 -d MAIND -u sbarkley -p ****** -r disk:SOL=$HOME/Documents/SOL -g 95% 150.251.112.38 &

where...
-z    - enables compression
-P    - enables bitmap caching (saves network traffic)
-x m  - disables eye-candy features
-a 16 - reduce colour pallete to 16 colours
-d    - domain to connect to
-u    - username
-p    - password
-r    - setup a shared folder
-g    - geometry (use W x H or percentage)

Slight problems with rdesktop not working 100% of the time. Now using xfreerdp. Seems better...

xfreerdp -g 90% --ignore-certificate --gdi sw -K -d wdcrhbp05 -u oraibm -p "`cat $HOME/scripts/.oraibm.password`" -T "wdcrhbp05_oraibm" --plugin cliprdr --plugin rdpdr --data disk:SOL:/home/bey9at77/Documents/SOL -- --plugin rdpsnd --data alsa -- 150.251.112.25 &

Reset your password bypassing password rules[edit]

must be done as root

echo "user:new_password" | chpasswd

Sum the sizes of all files of an ls listing[edit]

It'll check to see if the sum of filesizes corresponds with the df -g (or h) listing (can get messed up due to open but deleted files)

cd /oracle/export
df -g .
find . -name "*dmp*" -ls |  awk '{ SUM += $7} END { print SUM/1024/1024/1024 }'

Mount an iso image under Linux[edit]

mkdir -p /mnt/cdrom
mount -o loop /dev/cdrom /mnt/cdrom

How many processors on the machine?[edit]

  • AIX
lsdev -C|grep Process|wc -l
  • Solaris
psrinfo -v|grep "Status of processor"|wc -l
  • Linux
cat /proc/cpuinfo|grep processor|wc -l

Quick, simple, understandable example of how to use RRDTool[edit]

Use expect to respond automatically to interactive programs[edit]

#!/usr/bin/expect -f
spawn /usr/tivoli/tsm/client/oracle/bin64/tdpoconf passw -tdpo_optfile=/oracle/[lindex $argv 0]/admin/tdpo.opt
expect "assword:" {send "password\r"}
expect "assword:" {send "password\r"}
expect "assword:" {send "password\r"}

Use expect to allow file copy with scp (if ssh keys are not an option)[edit]

#!/usr/bin/expect -f
spawn scp /home/oracle/.profile oracle@hn512:/tmp/prfl
set pass "thepassword"
expect {
        password: {send "$pass\r" ; exp_continue}
        eof exit
}

Within a shell script set up simultaneous output to both terminal and a file using a FIFO (named pipes)[edit]

or "How to send shell output to screen/stdout as well as to a logfile using tee and redirection with exec"

examples here on unix.com

#!/bin/ksh

REDIR=test.redir
FIFO=test.pipe
[[ -e $FIFO ]] || mkfifo $FIFO

# make a new channel(3) and copy channel 1's destination as its own (does NOT POINT TO channel 1's destination)
# this allows the normal output to continue to STDOUT but also get printed to whatever file is attached to channel 3
exec 3>&1

# anything coming in on the pipe, send it to $REDIR and to channel 3
tee $REDIR <$FIFO >&3 &

# redirect STDOUT to the pipe
exec > $FIFO

echo "going to default output"
echo "forcing to channel 1" >&1
echo "forcing to channel 2" >&2
echo "forcing to channel 3" >&3

More elaborate example[edit]

found here on stackoverflow

#!/bin/sh

# Author: Harvey Chapman <hchapman _AT_ 3gfp.com>
# Description: POSIX shell functions that can be used with tee to simultaneously put
#              stderr and stdout to both a file and stdout
#
# Based on:
#    Re: How to redirect stderr and stdout to a file plus display at the same time
#    http://www.travishartwell.net/blog/2006/08/19_2220

#
# Original example function from Travis Hartwell's blog.
# Note: I've made minor changes to it.
example()
{
  OUTPUT_LOG=output.log
  OUTPUT_PIPE=output.pipe

  # This should really be -p to test that it's a pipe.
  if [ ! -e $OUTPUT_PIPE ]; then
      mkfifo $OUTPUT_PIPE
  fi

  # This should really be -f to test that it's a regular file.
  if [ -e $OUTPUT_LOG ]; then
      rm $OUTPUT_LOG
  fi

  exec 3>&1 4>&2
  tee $OUTPUT_LOG < $OUTPUT_PIPE >&3 &
  tpid=$!
  exec > $OUTPUT_PIPE 2>&1

  echo "This is on standard out"
  echo "This is on standard err" >&2

  exec 1>&3 3>&- 2>&4 4>&-
  wait $tpid

  rm $OUTPUT_PIPE
}

# A slightly reduced version of example()
example2()
{
  OUTPUT_LOG=output.log
  OUTPUT_PIPE=output.pipe

  rm -f $OUTPUT_PIPE
  mkfifo $OUTPUT_PIPE
  rm -f $OUTPUT_LOG

  tee $OUTPUT_LOG < $OUTPUT_PIPE &
  tpid=$!

  exec 3>&1 4>&2 >$OUTPUT_PIPE 2>&1

  echo "This is on standard out"
  echo "This is on standard err" >&2

  exec 1>&3 3>&- 2>&4 4>&-
  wait $tpid
  rm -f $OUTPUT_PIPE
}

#
# Logging methods based on above. See the example below for how to use them.
#

# Usage: start_logging [delete_existing_logfile]
start_logging()
{
  # Check to see if OUTPUT_LOG and OUTPUT_PIPE need to be defined.
  if [ -z "$OUTPUT_LOG" ]; then
    OUTPUT_LOG=output.log
  fi
  if [ -z "$OUTPUT_PIPE" ]; then
    OUTPUT_PIPE=output.pipe
  fi
  # Make sure that we're not already logging.
  if [ -n "$OUTPUT_PID" ]; then
    echo "Logging already started!"
    return 1
  fi

  # Always remove the log and pipe first.
  rm -f $OUTPUT_PIPE
  # Delete the logfile first if told to.
  if [ "$1" = delete_existing_logfile ]; then
    rm -f $OUTPUT_LOG
  fi

  mkfifo $OUTPUT_PIPE
  tee -a $OUTPUT_LOG < $OUTPUT_PIPE &
  OUTPUT_PID=$!

  exec 3>&1 4>&2 >$OUTPUT_PIPE 2>&1
}

stop_logging()
{
  # Make sure that we're currently logging.
  if [ -z "$OUTPUT_PID" ]; then
    echo "Logging not yet started!"
    return 1
  fi
  exec 1>&3 3>&- 2>&4 4>&-
  wait $OUTPUT_PID
  rm -f $OUTPUT_PIPE
  unset OUTPUT_PID
}

example3()
{
  start_logging
  #start_logging delete_existing_logfile
  echo "This is on standard out"
  echo "This is on standard err" >&2
  stop_logging
}

RedHat root filesystem has gone read-only[edit]

Kill all processes for a user[edit]

for prc in `ps -ef | grep -E "^ +[o]racle" | awk '{print $2}'`; do
    kill $prc
done

isRGHere[edit]

Checks if resource group is on this leg of an HACMP cluster. Returns 0 if true else 1.

#!/usr/bin/ksh

SCRIPT=`basename $0`

function rctest
{
exitcode=$1
msg=$2
if [ $exitcode -ne 0 ]; then
        echo "********************************************************************************"
        echo "\nScript $SCRIPT finished with errors."
        echo "$msg."
        echo "Returncode : $exitcode."
        echo "\n********************************************************************************"

        fi
exit $exitcode

}

RGINFO=/usr/es/sbin/cluster/utilities/clRGinfo
[[ ! -f $RGINFO ]] &&  rctest 1 "clRGinfo not found"

if [ $# -eq 1 ]
then
        RG=`echo $1 | cut -c 1-14`
else
        rctest 10  "Usage: `basename $0` <RG name>"
fi

$RGINFO |grep -qwp $RG ||  rctest 9 "$RG is not defined"

THISNODE=`/usr/es/sbin/cluster/utilities/get_local_nodename | cut -c 1-14`
$RGINFO |grep -wp $RG |grep -w $THISNODE |grep -wq ONLINE

AIX: add a user to a group[edit]

chgrpmem -m + oracle ibmtls

Find swear words in scripts by comparing it to a list found on the internet[edit]

wget "http://www.bannedwordlist.com/lists/swearWords.csv" -O /tmp/s ; for word in $(cat /tmp/s | sed -e 's/ /_/g' -e 's/,/ /g') ; do grep -wR $word *; done | less

grep -p (for paragraph) works on AIX but not on Linux or Solaris[edit]

Use awk instead

awk 'BEGIN {FS="\n" RS="\n\n"} /search pattern/ { do something }' <file>
/usr/xpg4/bin/awk 'BEGIN {RS="\n\n";FS="\n"} /AGRHDWQ1/ {print $2}' dsm.sys | awk '{print $NF}'

this prints the last word of the second line in the paragraph in dsm.sys that contains the search term AGRHDWQ1.
Or slightly simpler...

awk -v RS='' '/NHAPPLP1/' /etc/tsm/dsm.sys     # (use /usr/xpg4/bin/awk on Solaris)

or, case insensitively:

awk -v RS='' 'tolower($0) ~/so_u_clubqa_orx_d_cab/' /etc/tsm/dsm.sys

Using -v means you don't have to use a BEGIN section.

debug/redirect log of a shell[edit]

#!/usr/bin/ksh
exec 2>/tmp/mytest

Different ways of Iteration in korn shell with a while loop[edit]

IFS="|"
exec 0<$statfile
while read host db started stopped
do
    rrdfile="export_duration_${host}_${db}.rrd"
    $RRDTOOL update ${RRDDIR}/${rrdfile} $started:$started $stopped
done

or

while read host db started stopped
do
    rrdfile="export_duration_${host}_${db}.rrd"
    $RRDTOOL update ${RRDDIR}/${rrdfile} $started:$started $stopped
done <statfile

or

    cat $statfile | sort -nk4 | while IFS=\| read host db type started stopped
    do
        [[ "$stopped" == "" ]] && continue
        rrdfile="export_duration_${host}_${db}.rrd"
        $RRDTOOL update ${RRDDIR}/${rrdfile} ${started}:${started}:${stopped}
        [[ $? -ne 0 ]] && echo "nok: $?"
    done

Filesystem 100% full, what's taking up all the space?[edit]

find /oracle/endur -xdev -ls|sort -nr +6|head

or

/dev/esb01fs010001      1.00      0.00  100%     1838    69% /oracle
beuxdsysesb01:root[/root]# cd /oracle
beuxdsysesb01:root[/oracle]# du -gsx * | sort -n
0.00    checkpoints
0.00    flash_recovery_area
0.00    lost+found
0.00    oraInst.loc
0.00    oraInventory
0.09    admin
0.99    diag

cd diag and repeat until culprits are found

Show paged memory hogs on AIX[edit]

svmon -Pt20 | perl -e 'while(<>){print if($.==2||$&&&!$s++);$.=0 if(/^-+$/)}'

Capitalise the first letter of a word in Korn Shell[edit]

Not as easy as it sounds if it needs to work in non-ksh93 shells

function capit { 
    typeset -u first
    first=${1%"${1#?}"}
    printf "%s\n" "${first}${1#?}"
    return 0
}

or maybe more neatly done in Perl...
This will capitalise each word in a sentence passed into it

function capit { 
    echo "$1" |  perl -pe "s/([\w']+)/\u\L\1/g"
    return 0
}

Remove / rename a directory / file containing weird control characters[edit]

Use ls with -i to see inode listing

ls -bali

Use find with -inum to get the filename and -exec to remove it

find . -inum <inode from ls listing> -exec rm -f {} \;

Run a local script on a remote host[edit]

Doing it this way means we do not need to scp the shell over to the host before executing it!

ssh user@host 'sh' < your_script.sh

First of all, this command is a redirection: your shell will open the file your_script.sh and feed it as input to the ssh command. ssh, in turn, will tunnel its stdin to the remote command, namely, sh instance. And sh without arguments reads its script from stdin. So we got sh instance, which is launched on remote host, but reads commands from your local file.

Get a list of running instances - but only those started by the current user[edit]

This is the way I wanted to do it but there's an issue. Where does that spare } character come from? Anyone?

ps -ef | grep [p]mon | awk -v dbowner=$(id -un) '{ if ($1==dbowner) { gsub(/ora_pmon_/,"",$NF); print $NF; } }'

ps listing

$ ps -ef | grep [p]mon
  oracle 13304024        1   0   Jun 07      -  2:39 ora_pmon_reportk
  oracle 26018178        1   0   Jun 07      -  3:01 ora_pmon_dwh_perf
  oracle 29229432        1   0   Jun 07      -  2:30 ora_pmon_adso
 oraebso 18022994        1   0   Jun 07      -  2:38 ora_pmon_EBSO
  oracle 30278192        1   0   Jun 07      -  2:48 ora_pmon_owb112k

Results of above command

reportk
dwh_perf
adso
}
owb112k

Workaround 1. Send the ps listing to a file and work on it without pipes. Works but it's a bit long-winded especially as we have to clean up afterwards.

ps -ef | grep [p]mon>/tmp/results.$$ 2>/dev/null; awk -v dbowner=$(id -un) '{ if ($1==dbowner) { gsub(/ora_pmon_/,"",$NF); print $NF; } }' /tmp/results.$$; rm -f /tmp/results.$$

Workaround 2. Don't like the grep -v but until I find out where that } is coming from..

ps -ef | grep [p]mon | awk -v dbowner=$(id -un) '{ if ($1==dbowner) { gsub(/ora_pmon_/,"",$NF); print $NF; } }' | egrep -v 'grep|}|ASM'

Return a list of Oracle databases running on a list of remote servers[edit]

#!/bin/ksh

serverlist=`cat /home/tools/ini/system/oracle_servers | sort -n | tr "\n" " "`

if [ -z "${serverlist}" ]
then
    echo "no servers found" && exit 1
fi


for server in ${serverlist}
do
    ssh ${server} "ps -ef | grep [o]ra_pmon_" >/tmp/${server}.dblist
done

for server in ${serverlist}
do
    cat /tmp/${server}.dblist | awk -F_ -v SRV=${server} 'BEGIN {print SRV ":"} {print $NF}' | tr "\n" " "
    echo
done

Clever trick to check whether SQL output needs sending to someone[edit]

Using an exit status from SQL*Plus back to the shell so we can decide what to do. Nice one!

#!/bin/bash
tempfile=/tmp/audit_locked_accounts_$ORACLE_SID.txt

# Start sqlplus and check for locked accounts
sqlplus -S "/ as sysdba" << EOF > $tempfile
set pages 0
select 'The following accounts were found to be unlocked and should not be'
from dual;

def exit_status = 0
col xs new_value exit_status

select username
,      account_status
,      1 as xs
from   dba_users
where  account_status != 'LOCKED'
and    username in ('HR', 'SCOTT', 'OUTLN', 'MDSYS', 'CTXSYS')
/
exit &exit_status
EOF

# If the exit status of sqlplus was not 0 then we will send an email
if [ $? != 0 ]; then
    mail -s "Accounts Unlocked in $ORACLE_SID" oracle < $tempfile
fi

Check RMAN logfiles for errors from cron every day[edit]

00 09 * * * /home/tools/scripts/oracle/dosh 'find /home/tools/logs/rman -name "*online.log" -mtime -1 -exec sed -ne "/^RMAN-/,/^$/p" {} \\; -ls' | mailx
 -s 'RMAN errors last night' [email protected]
/home/ibmtools/scripts/oracle/dosh 'find /oracle/export -name "expdp*log" -mtime -1 -exec grep ORA- {} \; -ls' | mailx -s 'Datapump errors for Baxter last night' [email protected]

An alternative to getopts[edit]

These methods have the advantage of allowing arguments of any length not just 1 character

countArgs=$#
while [[ $# -gt 0 ]]
do
    idx1=$($ECHO $1|$GREP "="|wc -l)
    if [[ $idx1 -gt 0 ]]; then
        key=$($ECHO $1|$CUT -d '=' -f 1)
        value=$($ECHO $1|$CUT -d '=' -f 2)
    else
        key=$($ECHO $1|$CUT -d '=' -f 1)
        idx2=$($ECHO $1|$GREP "^-"|wc -l)
        if [[ $idx2 -eq 0 ]]; then
            $ECHO -e "\n ERROR: $1 is an unsupported argument passed to agentDeploy.sh.\n"  
            usage
            exit 1
        fi
    fi

    case "$key" in
    -help)
        if [[ $upgradeFlag ]]; then
            upgradeUsage
        else
            freshUsage
        fi
        exit 0;;
    AGENT_BASE_DIR)
        agentBaseDir=$($ECHO $value|$SED 's/\/$//')
        checkBaseFlag=TRUE;;
    OMS_HOST)
        omsHost=$value
        checkOMSHost=TRUE;;
    EM_UPLOAD_PORT)
        omsPort=$value
        checkOMSPort=TRUE;;
    AGENT_INSTANCE_HOME)
        instHome=$($ECHO $value | $SED 's/\/$//');;
    AGENT_REGISTRATION_PASSWORD)
        pswd=$value;;
    s_encrSecurePwd)
        pswd=$value;;  
    RESPONSE_FILE)
        rspFlag=TRUE  
        rspLoc=$value;;
    OLD_AGENT_VERSION)
        oldAgentVersion=$value;;            
    OLDHOME)
        oldHome=$value;;    
    -debug)
        debugSwitch=TRUE;;
    -forceConfigure)
        forceFlag=TRUE;;
    -configOnly)
        configFlag=TRUE    
        validationFlag=TRUE;;
    -agentImageLocation)
        archiveLoc=$value
        checkArchiveFlag=TRUE;;
    -invPtrLoc) shift
        ptrLoc=$1;;
    -Upgrade)
        UpgradeFlag=TRUE
        validFlag=TRUE;;
    INVENTORY_LOCATION)
        validFlag=TRUE;;
    b_forceInstCheck)
        validFlag=TRUE
        forcefullFlag=TRUE;;
    -prereqOnly)
        validationFlag=TRUE
        prereqFlag=TRUE;;
    -executeRootsh)
        validFlag=TRUE;;
    *)  idx=$($ECHO $1|$GREP "^-"|wc -l)
        if [[ $idx -eq 0 ]]; then
            validFlag=TRUE
        else
            $ECHO -e "\n ERROR: Invalid argument $key passed."
            usage
            exit 1          
        fi
    esac
    shift
done

another way - found in /etc/init.d/functions (daemon function) in Fedora

    while [ "$1" != "${1##[-+]}" ]; do
        case $1 in
        '')
            echo $"$0: Usage: daemon [+/-nicelevel] {program}" "[arg1]..."
            return 1
            ;;
        --check)
            base=$2
            gotbase="yes"
            shift 2
            ;;
        --check=?*)
            base=${1#--check=}
            gotbase="yes"
            shift
            ;;
        --user)
            user=$2
            shift 2
            ;;
        --user=?*)
            user=${1#--user=}
            shift
            ;;
        --pidfile)
            pid_file=$2
            shift 2
            ;;
        --pidfile=?*)
            pid_file=${1#--pidfile=}
            shift
            ;;
        --force)
            force="force"
            shift
            ;;
        [-+][0-9]*)
            nice="nice -n $1"
            shift
            ;;
        *)
            echo $"$0: Usage: daemon [+/-nicelevel] {program}" "[arg1]..."
            return 1
            ;;
      esac
    done

another way - found in adstrtal.sh (middleware start script for EBS)

#
# Parse Arguments
#

for nxtarg in $*
do
  arg=`echo $nxtarg | sed 's/^//'`

  case $arg in
    -secureapps)    if test "$secureapps" = "" ; then
                       secureapps=$arg
                    else
                       echo "$0: Duplicate Argument passed : $arg"
                       usage
                    fi
                ;;
    -nodbchk)       if test "$nodbchk" = "" ; then
                       nodbchk=$arg
                    else
                       echo "$0: Duplicate Argument passed : $arg"
                       usage
                    fi
                ;;
    -nopromptmsg)   if test "$nopromptmsg" = "" ; then
                       nopromptmsg=$arg
                    else
                       echo "$0: Duplicate Argument passed : $arg"
                       usage
                    fi
                ;;
    *)              if test "$unpw" = "" ; then
                       unpw=$arg
                    else
                       echo "$0: Duplicate Argument passed : $arg"
                       usage
                    fi
  esac
done

and another in adautocfg.sh

for myarg in $*
do

  arg=`echo $myarg | sed 's/^-//'`
  case $arg in
    appspass=*)
            appspass=`echo $arg | sed 's/appspass=//g'`
            shift
            ;;
    nocustom)
            myparams="$myparams $arg"
            shift
            ;;
    noversionchecks)
            myparams="$myparams $arg"
            shift
            ;;
    promptmsg=*)
            promptmsg=`echo $arg | sed 's/promptmsg=//g'`
            shift
            ;;
        *)  echo "$0: unrecognized action specified"
            exit 1
  esac
done

Run a script on multiple servers[edit]

#!/bin/ksh
# ==============================================================================
# Name         : dosh   (Distributed Oracle SHell)
# Description  : Runs a command on all Oracle servers
#
# Parameters   : h - displays help
#                v - verbose (default, like all unix commands is silent)
#                c - command to be executed
#
# Example      : ./dosh -v -c 'ls -al'
#
# Modification History
# ====================
# When      Who               What
# ========= ================= ==================================================
# 08-FEB-13 Stuart Barkley    Created
# ==============================================================================

# --------------------------------------------------------------------------
# this list of servers is generated by the DBAMON tool so will be up to date
# --------------------------------------------------------------------------
serverfile=/home/ibmtools/etc/oracle/oracle_servers
[[ -z "${serverfile}" ]] && echo "Server list ${serverfile} not found" && exit 1

serverlist=`cat ${serverfile} | sort -n | tr "\n" " "`


# -------------------------
# get the arguments, if any
# -------------------------
while getopts "hvc:" OPT
do
    case "$OPT" in
    h) echo "\nUsage: $0 [-v] [-h] -c '<command_to_be_executed_remotely>'\n";
       exit;
       ;;
    v) VERBOSE="Y";
       ;;
    c) CMMND=$OPTARG;
       ;;
    *) echo "\nUsage: $0 [-v] [-h] -c '<command_to_be_executed_remotely>'\n";
       exit;
       ;;
    esac
done
shift $((OPTIND-1))
VERBOSE=${VERBOSE:-"N"}


# --------------------------------
# check we have required arguments
# --------------------------------
[[ -z $CMMND ]] && echo "Enter command to be executed like this: $0 -c 'ls -al'" && exit 1


# ----------------------------
# loop over the remote servers
# ----------------------------
for server in ${serverlist}
do
    if [[ "$VERBOSE" == "Y" ]]; then
        echo ${server} `date +'%d-%b-%Y %H:%M:%S'`
        echo "------------------------------------"
        set -x
    fi
    ssh ${server} "$CMMND"
    set +x
    [[ "$VERBOSE" == "Y" ]] && echo
done

to be investigated... this one might be cleverer than mine...

tmpdir=${TMPDIR:-/tmp}/pssh.$$
count=0
while userhost; do
    ssh -n -o BatchMode=yes ${userhost} 'uname -a' > ${tmpdir}/${userhost} 2>&1 &
    count=`expr $count + 1`
done < userhost.lst
while [ $count -gt 0 ]; do
    wait $pids
    count=`expr $count - 1`
done
echo "Output for hosts are in $tmpdir"



improved version...
just escape double quotes and dollar signs...

#!/bin/ksh
# ==============================================================================
# Name         : dosh   (Distributed Oracle SHell)
# Description  : Runs a command on all Oracle servers
#
# Parameters   : h - displays help
#                v - verbose (default, like all unix commands is silent)
#                c - command to be executed
#
# Example      : ./dosh -v -c 'ls -al'
#
# Modification History
# ====================
# When      Who               What
# ========= ================= ==================================================
# 08-FEB-13 Stuart Barkley    Created
# 08-JUL-15 Stuart Barkley    Background execution mode
# ==============================================================================
# --------------------------------------------------------------------------
# this list of servers is generated by the DBAMON tool so will be up to date
# --------------------------------------------------------------------------
serverfile=/home/ibmtools/etc/oracle/oracle_servers
[[ -z "${serverfile}" ]] && echo "Server list ${serverfile} not found" && exit 1

serverlist=`cat ${serverfile} | sort -n | tr "\n" " "`


# -------------------------
# get the arguments, if any
# -------------------------
while getopts "hbvc:" OPT
do
    case "$OPT" in
    h) echo "\nUsage: $0 [-b] [-v] [-h] -c '<command_to_be_executed_remotely>'\n";
       exit;
       ;;
    b) BACKGROUND="Y";
       ;;
    v) VERBOSE="Y";
       ;;
    c) CMMND=$OPTARG;
       ;;
    *) echo "\nUsage: $0 [-b] [-v] [-h] -c '<command_to_be_executed_remotely>'\n";
       exit;
       ;;
    esac
done
shift $((OPTIND-1))
VERBOSE=${VERBOSE:-"N"}


# --------------------------------
# check we have required arguments
# --------------------------------
[[ -z $CMMND ]] && echo "Enter command to be executed like this: $0 -c 'ls -al'" && exit 1


# ---------------------------------
# put the thing to be run in a file
# ---------------------------------
printf "%s\n" "$CMMND" > /tmp/dosh.$$


# ----------------------------
# loop over the remote servers
# ----------------------------
for server in ${serverlist}
do
    if [[ "$VERBOSE" == "Y" ]]; then
        printf "%s\n" ${server} `date +'%d-%b-%Y %H:%M:%S'`
        printf "%s\n" "------------------------------------"
        set -x
    fi
    scp -q /tmp/dosh.$$ ${server}:/tmp/
    if [[ "$BACKGROUND" == "Y" ]]; then
        ssh -n -o BatchMode=yes ${server} "ksh /tmp/dosh.$$; rm -f /tmp/dosh.$$"> /tmp/dosh_${server}.out 2>&1 &
    else
        ssh -n -o BatchMode=yes ${server} "ksh /tmp/dosh.$$; rm -f /tmp/dosh.$$"
    fi
    set +x
    [[ "$VERBOSE" == "Y" ]] && echo
done
rm -f /tmp/dosh.$$

[[ "$BACKGROUND" == "Y" ]] && printf "%s\n" "Type 'ls -altr /tmp/dosh*out' to see output from the commands"

How can a shell script find out what directory it is in?[edit]

basename $0 does not always give the desired answer (might give "./"!

DIR="$(cd "$(dirname "$0")" && pwd)"

Array processing[edit]

array=(1 2 3)
unset array[2]
echo ${array[2]}          # null
indices=(${!array[@]})    # create an array of the indices of "array"
size=${#indices[@]}       # the size of "array" is the number of indices into it
size=${#array[@]}         # same
echo ${array[@]: -1}      # you can use slices to get array elements, -1 is the last one, etc.
for element in ${array[@]}; do    # iterate over the array without an index

for index in ${indices[@]}        # iterate over the array WITH an index
do
    echo "Index: ${index}, Element: ${array[index]}"
done

for index in ${!array[@]}         # iterate over the array WITH an index, directly

array+=("new element")    # append a new element without referring to an index
((counter++))             # shorter than ((counter=counter+1)) or ((counter+=1))
if [[ $var == 3 ]]        # you can use the more "natural" comparison operators inside double square brackets
while [[ $var < 11 ]]     # another example
echo ${array[${index}-1]  # math inside an array subscript

Send an email by talking directly to an smtp server[edit]

#!/bin/bash
telnet smtp.domain.com 25 <<EOTXT>>/tmp/smtp.log
HELO me.domain.com
MAIL FROM:<[email protected]>
RCPT TO:<[email protected]>
DATA
From: Stuart <[email protected]>
To: Anne <[email protected]>
Subject: testing smtp email

Hello, this should appear in the body
.
QUIT
EOTXT

Send an email by talking directly to an smtp server via file descriptor (no telnet! this time), adding authentication[edit]

#!/bin/bash

#
# mail.sh
#
# 2008 - Mike Golvach - [email protected]
# 2010 - Rayber
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

if [ $# -ne 7 ]
then
echo "Usage: $0 FromAdress ToAdress Domain MailServer MailTextFile AuthEmail AuthPass"
exit 1
fi

from=$1
to=$2
domain=$3
mailserver=$4
mailtext=$5
authemail=`echo $6|openssl enc -base64|awk 'sub("..$", "")'`
authpass=`echo $7|openssl enc -base64|awk 'sub("..$", "")'`

if [ ! -f $mailtext ]
then
echo "Cannot find your mail text file. Exiting..."
exit 1
fi

exec 9<>/dev/tcp/$mailserver/25
echo "HELO $domain" >&9
read -r temp <&9
echo "$temp"
echo "auth login" >&9
read -r temp <&9
echo "$authemail" >&9
read -r temp <&9
echo "$authpass" >&9
read -r temp <&9
echo "Mail From: $from" >&9
read -r temp <&9
echo "$temp"
echo "Rcpt To: $to" >&9
read -r temp <&9
echo "$temp"
echo "Data" >&9
read -r temp <&9
echo "$temp"
cat $mailtext >&9
echo "." >&9
read -r temp <&9
echo "$temp"
echo "quit" >&9
read -r temp <&9
echo "$temp"
9>&-
9<&-
echo "All Done Sending Email. See above for errors"
exit 0

rsync examples[edit]

Also see Distribute files to multiple servers using rsync and ssh

#!/bin/sh
ssh  <remote_host> '/bin/mkdir -p /etc /etc/rc.config.d /etc/security /etc/mail'
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/passwd /etc/passwd.post /etc/group /etc/hosts /etc/services /etc/resolv.conf /etc/exclude.rootvg <remote_host>:/etc
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/hosts.allow.xcat <remote_host>:/etc/hosts.allow
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/rc.config.d/sap <remote_host>:/etc/rc.config.d
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/security/group /etc/security/limits /etc/security/login.cfg /etc/security/passwd /etc/security/user <remote_host>:/etc/security
rsync --rsync-path /usr/bin/rsync -Liprogtz --out-format=%f%L  /etc/mail/sendmail.cf <remote_host>:/etc/mail

rsync -av --progress /home/ibmtools/scripts/oracle/* benouerp07:/home/ibmtools/scripts/oracle/

Handy aliases[edit]

Strip out comments and blank lines from a file

alias strip='grep -Ev '\''^(#|$)'\'''

Does a ps and a grep

alias psg='ps -ef | grep -v $$ | grep -i '

Getting a decent listing of filesystem space available. It is ordered such that the filesystems with no space left are at the end.

OS=$(uname -s)
[[ "$OS" == "SunOS" ]] && alias dfg='df -h|sed -e '1d'|sort -n -k5|awk '\'' BEGIN {printf("%-35s%-10s%-10s%-6s%-30s\n","Filesystem","Total","Free","%Used","Mounted on")} {printf("%-35s%-10s%-10s%-6s%-30s\n",$1,$2,$4,$5,$6)}'\'''
[[ "$OS" == "AIX" ]]   && alias dfg='df -g|sed -e '1d'|sort -n -k4|awk '\'' BEGIN {printf("%-35s%-10s%-10s%-6s%-30s\n","Filesystem","Total GB","Free","%Used","Mounted on")} {printf("%-35s%-10s%-10s%-6s%-30s\n",$1,$2,$3,$4,$7)}'\'''

A handy way of listing subdirectories and their files

alias filetree="find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'"

Watch progress of a copy

alias cpProgress="rsync --progress -ravz"
Reboots Linksys router
alias rebootlinksys="curl -u 'admin:password' 'http://192.168.1.2/setup.cgi?todo=reboot'"

Nice one for bash. Colour codes the prompt depending on the outcome of the previous command

bash_prompt_command()
{
    RTN=$?
    prevCmd=$(prevCmd $RTN)
}
PROMPT_COMMAND=bash_prompt_command
prevCmd()
{
    if [ $1 == 0 ] ; then
        echo $GREEN
    else
        echo $RED
    fi
}
if [ $(tput colors) -gt 0 ] ; then
    RED=$(tput setaf 1)
    GREEN=$(tput setaf 2)
    RST=$(tput op)
fi
export PS1="\[\e[36m\]\u.\h.\W\[\e[0m\]\[\$prevCmd\]>\[$RST\]"

Mmmm, to be looked into. Executes remote commands on a unix box using curl.

#/bin/sh
#
# WAG320N-HACK
# Ver. 1.0
# 12/09/2010
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Set username and password in the form of "username:password"
# example: "admin:admin"
my_access="admin:admin"

# Parameters test
if [ -z "$1" ]
then
  echo "wag320n-hack.sh: missing remote command"
  echo "usage: wag320n-hack.sh <remote command>"
  echo "example: wag320n-hack.sh /bin/ls -la /usr/sbin"
  echo "Note: always use full path"
  echo ""
  echo "wag320n-hack.sh - Ver. 1.0 - 12/09/2010"
  echo "Licensed under GPL V. 3"
  echo ""
  exit 0
fi

# Get the command
my_command="ping_size="'$('"$@"' 1>&2)'

curl -s -G -u "$my_access" --data-urlencode 'todo=ping_test' --data-urlencode 'this_file=Diagnostics.htm' --data-urlencode 'next_file=Ping.htm' --data-urlencode 'c4_ping_ipaddr=192.168.1.1' --data-urlencode 'ping_timeout=5000' --data-urlencode 'ping_interval=1000' --data-urlencode 'ping_number=1' --data-urlencode "$my_command" http://192.168.1.1/setup.cgi | sed -e '/HTTP\/1.0 200 OK/q'

How to configure SSH with public/private keys[edit]

Use SSH config file[edit]

Host server10
  Hostname 1.2.3.4
  IdentityFile ~/.ssh/id_dsa
  user foobar
  Port 30000
  ForwardX11Trusted yes
  TCPKeepAlive yes

then just connect using

ssh server10

A decent sed tutorial[edit]

From grymoire.com

A decent korn/bash shell tutorial[edit]

From dartmouth.edu Reproduced here just in case it disappears! Advanced shell scripting

trap[edit]

     Example Handling Traps With ksh - Discussion of the kill command


EXAMPLE TEMPLATE:


PRODUCT:    HP-UX 11iV1 Version B.11.11
            HP Tru64 V5.1B PK4
            Sun/Solaris SunOS V5.8
            Linux 2.6 kernel


COMPONENT:  ksh


SOURCE:     Philippe Vouters
            Fontainebleau/France


LOW COST HIGH-TECH PRODUCTS:  http://techno-star.fr


OVERVIEW:

The ksh script below shows how to eventually handle traps in the situation 
where someone might try to kill a script by killing individual commands run 
by that script or the entire process group a script is running in. The kill 
command (usually a shell builtin) may be used to send a signal to a process 
group (with the -<pid> syntax) or an individual process. The example ksh 
script below runs /bin/sleep as the foreground process, the example ksh 
scripts immediately returns when the /bin/sleep process has terminated. Most 
signals sent to the shell are ignored until after the foreground process 
terminates. This is in order to avoid creating zombie processes. Therefore a 
kill <pid> on the example ksh script waits for the termination of the 
/bin/sleep process.

The status value $? in the trap refers to the exit status of the command to run 
and therefore is the exit status of the /bin/sleep process. The called function 
in the trap handler shows how to correctly examine the effect of the kill 
command on the shell or it's children.

To examine the value of $? in a trap handler means that you must understand what
it can be set and how different signals delivered to either the shell or the 
foreground process (or the process group) might affect the value of $?.

The example shell script prints $? using echo but it does not perform tests on 
the value of $?. For a complete solution when attempting to trap signals in a 
shell you would also need code that examined the value of $? after the 
foreground process had completed.


*** CAUTION ***

This sample script has been tested using HP-UX B.11.11, HP Tru64 V5.1B PK4, 
SunOS V5.8 and Fedora Core 4 (homed version of Red Hat Linux).  However, we
cannot guarantee its effectiveness because of the possibility of error in 
transmitting or implementing it. It is meant to be used as a template for 
writing your own scripts, and may require modification for use on your system. 


SCRIPT NOTES:

To notice that the ksh script and /bin/sleep share the same process group
identifier (PGID), issue the following commands:

[philippe@victor ~]$ who
philippe :0           Jan 10 10:16
philippe pts/1        Jan 10 21:30 (:0.0)
philippe pts/2        Jan 10 21:30 (:0.0)
[philippe@victor ~]$ tty
/dev/pts/1
[philippe@victor ~]$ ps -j -t pts/2
  PID  PGID   SID TTY          TIME CMD
11072 11072 11072 pts/2    00:00:00 bash
11113 11113 11072 pts/2    00:00:00 ksh
11116 11113 11072 pts/2    00:00:00 sleep

In this case sending kill -INT -11113 will send SIGINT to the process group 
11113. Both of the ksh and sleep processes are contained within this process 
group.

Important Note:

On HP-UX, you have to $ export UNIX95=1 in order to be able to use the
-j option of the ps command.


SCRIPT:

                             COPYRIGHT (C) 2005 BY
                              HEWLETT-PACKARD COMPANY
                                ALL RIGHTS RESERVED.

     THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
     ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE INCLUSION
     OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY OTHER COPIES
     THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER
     PERSON.  NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.

     THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
     SHOULD NOT BE CONSTRUED AS A COMMITMENT BY HEWLETT-PACKARD COMPANY.

     HP ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
     SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY HP.

     NO RESPONSIBILITY IS ASSUMED FOR THE USE OR RELIABILITY OF SOFTWARE
     ON EQUIPMENT THAT IS NOT SUPPLIED BY HEWLETT-PACKARD COMPANY.

     SUPPORT FOR THIS SOFTWARE IS NOT COVERED UNDER ANY HP SOFTWARE
     PRODUCT SUPPORT CONTRACT, BUT MAY BE PROVIDED UNDER THE TERMS OF THE
     CONSULTING AGREEMENT UNDER WHICH THIS SOFTWARE WAS DEVELOPED.

#!/bin/ksh
function handle_signal
{
        print -n "pid $$ recieved $2 "
        if [[ $1 = 0 ]];then
            print but foreground command ended successfully
        else
                if [[ $1 = $3 ]];then
                    print and so did the last foreground command
                else
                    print -n "and the exit status of the last foreground "
                    print command was $1
                fi
        fi
        # Kill our process group and then ourselves with SIGTERM, giving a 
        # pid of 0 sends the signal to our process group. Killing the process
        # group should kill us as well, this assumes that SIGTERM is not 
        # handled by any process in the process group.
        #
        # This code could be replaced with an exit with an exit value that
        # would indicate what the problem was to the caller. That is replace 
        # these two lines with:
        #
        # exit $3
        #
        # or a specific exit code could be used.
        #
        kill -TERM 0
        kill -TERM $$
        }
OS=$(uname -a | awk '{print $1}')
if [[ "$OS" = "Linux" ]]; then
    offset=256
elif [[ ("$OS" = "HP-UX") || 
        ("$OS" = "SunOS") || 
        ("$OS" = "OSF1") ]]; then
   offset=128
fi
trap 'RC=$?; handle_signal $RC SIGINT $offset+2' INT
trap 'RC=$?; handle_signal $RC SIGQUIT $offset+3' QUIT
/bin/sleep 20
echo $?

DNS not working[edit]

Ping to an IP address works

ping 74.125.136.103

but this doesn't

ping www.google.com

Check resolv.conf

cat /etc/resolv.conf
nameserver 95.130.132.17
nameserver 95.130.132.18

I had changed internet provider and forgot to update this. Just to set it to the router address and let that do the resolution

nameserver 192.168.1.1

File descriptors[edit]

exec 3<> /tmp/foo  #open fd 3 for r/w
echo "test" >&3
exec 3>&- #close fd 3.
exec 3<> myfile.txt
while read line <&3
do {
  echo "$line"
  (( Lines++ ));                   #  Incremented values of this variable
                                   #+ accessible outside loop.
                                   #  No subshell, no problem.
}
done
exec 3>&-

echo "Number of lines read = $Lines"     # 8

Mmm. See our output and also tee it to a log file!

#!/bin/bash

echo hello

if test -t 1; then
    # Stdout is a terminal.
    exec >log
else
    # Stdout is not a terminal.
    npipe=/tmp/$$.tmp
    trap "rm -f $npipe" EXIT
    mknod $npipe p
    tee <$npipe log &
    exec 1>&-
    exec 1>$npipe
fi

echo goodbye

Create new image with kvm[edit]

Ref: http://www.cyberciti.biz/faq/kvm-virtualization-in-redhat-centos-scientific-linux-6/
Build an empty space for a CentOS virtual machine

qemu-img create -f qcow2 centos.img 12G

Tried creating image with

sudo virt-install -n CentOS --description "Trying out CentOS" --ram=1024 --vcpus=1 --cpu host --hvm --cdrom /home/bey9at77/Downloads/c6-x86_64-20130910-1.qcow2 --graphics vnc --disk path=/var/lib/libvirt/images/centos.img,bus=virtio,size=10

gives error

Starting install...
Allocating 'centos.img'                                                                                                                                                                                               |  10 GB     00:00     
ERROR    internal error Process exited while reading console log output: char device redirected to /dev/pts/1
qemu-kvm: -drive file=/home/bey9at77/Downloads/c6-x86_64-20130910-1.qcow2.bz2,if=none,media=cdrom,id=drive-ide0-1-0,readonly=on,format=raw: could not open disk image /home/bey9at77/Downloads/c6-x86_64-20130910-1.qcow2: Permission denied

rpm / yum commands[edit]

Install an RPM Package[edit]

rpm -ivh pidgin-2.7.9-5.el6.2.i686.rpm

-i - install
-v - verbose
-h - print progress hashes

Check dependencies of RPM Package before Installing[edit]

rpm -qpR BitTorrent-5.2.2-1-Python2.4.noarch.rpm

-q - query
-p - list package capabilities
-R - list dependent package capabilities

Install RPM Package with all dependencies[edit]

yum install BitTorrent-5.2.2-1-Python2.4.noarch.rpm

Install RPM Package with all dependencies (when RPM has been downloaded to local machine)[edit]

yum localinstall BitTorrent-5.2.2-1-Python2.4.noarch.rpm

Force Install a RPM Package without dependencies[edit]

Package will not work if dependencies are required

rpm -ivh --nodeps BitTorrent-5.2.2-1-Python2.4.noarch.rpm

Check an Installed RPM Package[edit]

rpm -q BitTorrent

List all files of an installed RPM package[edit]

rpm -ql BitTorrent

List All Installed RPM Packages[edit]

rpm -qa

Query information about an installed RPM package[edit]

rpm -qi vsftpd

Query information about a not yet installed RPM package[edit]

rpm -qip sqlbuddy-1.3.3-1.noarch.rpm

(Forcibly) Remove an RPM Package[edit]

Use package name (as seen in -qi above), not full name

rpm -ev (--nodeps) vsftpd

Query a file that was installed as part of an RPM Package (which package contained this file)[edit]

rpm -qf /usr/bin/htpasswd

Verify an RPM package[edit]

Compares information of installed files of the package against the rpm database

rpm -Vp sqlbuddy-1.3.3-1.noarch.rpm

Rebuild corrupted RPM database[edit]

cd /var/lib
rm __db*
rpm --rebuilddb
rpmdb_verify Packages

Install rpmforge repository[edit]

  • Download rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
  • Import the key
sudo rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt
  • Install the repository
sudo rpm -i rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
  • Check the installation
rpm -K rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
  • Test it
sudo yum install terminator

Install rpmfusion repository[edit]

su -c 'yum localinstall --nogpgcheck http://download1.rpmfusion.org/free/el/updates/6/i386/rpmfusion-free-release-6-1.noarch.rpm http://download1.rpmfusion.org/nonfree/el/updates/6/i386/rpmfusion-nonfree-release-6-1.noarch.rpm'

config file for yum[edit]

Checkout this file for global yum config

/etc/sysconfig/yum-cron-background

Setup Oracle Enterprise Linux (RedHat) with yum server[edit]

You need to download the yum .repo file from the server, as per the steps below. After this, you need to enable a flag in the .repo file as per your operating system version. Having done these two steps, when you run yum install <pkgname> command on your linux box, the Oracle's yum server will be scanned, the dependent & the relevant rpm's will be download and installed for you.

cd /etc/yum.repos.d

To download files here

wget http://public-yum.oracle.com/public-yum-el5.repo

A file named public-yum-el5.repo will be created in your directory
Edit this file and enter enabled=1 against the operating systems which is relevant to you

vi public-yum-el5.repo

Next run the yum command

yum install package-name

To change to static IP address (Raspberry Pi)[edit]

As root:

cd /etc/networks
vi interfaces

replace the line “iface eth0 inet dhcp” with

iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1

You should also take a look at the file /etc/resolv.conf and check it has a nameserver entry (probably pointing at your default gateway) or direct to your ISP name servers.

nameserver 192.168.1.1

Troubleshoot wireless network problems[edit]

Short summary of all the things you need to do in just few lines

root@kali:~# iw dev
root@kali:~# ip link set wlan0 up
root@kali:~# iw wlan0 scan
root@kali:~# wpa_passphrase blackMOREOps >> /etc/wpa_supplicant.conf
root@kali:~# wpa_supplicant -i wlan0 -c /etc/wpa_supplicant.conf
root@kali:~# iw wlan0 link
root@kali:~# dhclient wlan0
root@kali:~# ping 8.8.8.8
(Where wlan0 is wifi adapter and blackMOREOps is SSID)
(Add Routing manually)
root@kali:~# ip route add default via 10.0.0.138 dev wlan0

To change to static IP address (Redhat/CentOS)[edit]

As root:

vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=STATIC
IPADDR=192.168.1.111
NETMASK=255.255.255.0
GATEWAY=192.168.1.1
ONBOOT=yes
DNS1=8.8.8.8
DNS2=8.8.4.4

Resrart the network interface

/etc/init.d/network stop
/etc/init.d/network start
or
service network restart

Check name server entry in resolv.conf

vi /etc/resolv.conf
nameserver 192.168.1.1

Enable processes / services to start at boot time[edit]

sudo chkconfig httpd on
sudo chkconfig mysqld on

Run a command on lots of servers in parallel[edit]

This is a damn fine AIX utility - part of the CSM Distributed Shell.

dsh -a "ls -al /etc/apache2/*conf"

will list the Apache configuration file on all reachable servers (nodes)

Download a gzip file and pipe it into tar[edit]

cd ~ && wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf -

Check in a script to make sure it is run only by root[edit]

RUID=`/usr/bin/id|$AWK -F\( '{print $1}'|$AWK -F\= '{print $2}'`
if [ ${RUID} != "0" ];then
   $ECHO "This script must be executed as root"
   exit 1
fi

Set terminal to use Backspace key to erase previous character instead of Control-H[edit]

Been looking for this for a long time.
You can put:

stty erase <CTRL-V><Backspace key>

in your .profile but this will be ruined if you do a copy/paste into another file.
I wanted a way of doing this without entering the control character in the .profile. Finally stumbled upon it. And it's so simple. Just escape the caret!

stty erase \^?

Put this in the .profile. It's copy/pastable and it works!
If you want CTRL-H to be your erase character, just do this:

stty erase \^H

Play with the terminal settings and reset them again either side of requesting a password[edit]

The -g option of stty gives a compact list of all the settings or the terminal and can be used as input to stty

OLDCONFIG=`stty -g`          # save terminal configuration
stty -echo                   # turn character echoing off
echo "Enter password: \c"
read PASSWD                  # get the password
stty $OLDCONFIG              # restore terminal configuration

Reset terminal to "sane" characteristics[edit]

If you've done a cat of a binary file or something else weird and your terminal is left in a mess, the following key sequence should bring it back to normal

<CTRL-J>stty sane<CTRL-J>

Install OpenOffice on RedHat Enterprise when yum install doesn't![edit]

Download Package

wget http://sourceforge.net/projects/openofficeorg.mirror/files/4.0.1/binaries/en-US/Apache_OpenOffice_4.0.1_Linux_x86-64_install-rpm_en-US.tar.gz/download -O Apache_OpenOffice_4.0.1_Linux_x86-64_install-rpm_en-US.tar.gz

Change to root

sudo su -

Remove the old stuff

yum remove openoffice* libreoffice*

Extract Package

tar -xvf Apache_OpenOffice_4.0.1*
cd en-US

Install Package and exit root

rpm -Uvh RPMS/*.rpm RPMS/desktop-integration/openoffice4.0-redhat-*.rpm
exit

Start it

openoffice4

What does this do?[edit]

while IFS= read -r line; do
    echo "[$(date "+%F %T")] - $line"
done < <(iwevent)

or

while IFS= read -r line; do
    printf "%s\n%s\n" "$line" "Yohooo! One more package."
done < <(tcpdump -i any -nS)

List of Special Characters and what they mean[edit]

From Bruce Barnett

Character	Where	Meaning
<RETURN>	csh, sh	Execute command
#	csh, sh, ASCII files	Start a comment
<SPACE>	csh, sh	Argument separator
`	csh, sh	Command substitution
"	csh, sh	Weak Quotes
'	csh, sh	Strong Quotes
\	csh, sh	Single Character Quote
variable	sh, csh	Variable
variable	csh, sh	Same as variable
|	csh, sh	Pipe character
^	sh	Pipe Character
&	csh, sh	Run program in background
?	csh, sh	Match one character
*	csh, sh	Match any number of characters
;	csh, sh	Command separator
;;	sh	End of Case statement
~	csh	Home Directory
~user	csh	User's Home Directory
!	csh	History of Commands
-	Programs	Start of optional argument
$#	csh, sh	Number of arguments to script
$*	csh, sh	Arguments to script
$@	sh	Original arguments to script
$-	sh	Flags passed to shell
$?	sh	Status of previous command
$$	sh	Process identification number
$!	sh	PID of last background job
&&	sh	Short-circuit AND
||	sh	Short-circuit OR
.	csh, sh	Typ. filename extension
.	sh	Source a file and execute as command
:	sh	Nothing command
:	sh	Separates Values in environment variables
:	csh	Variable modifier
Character	Where	Meaning
[ ]	csh, sh	Match range of characters
[ ]	sh	Test
%job	csh	Identifies job Number
(cmd;cmd)	csh. sh	Runs cmd;cmd as a sub-shell
{ }	csh	In-line expansions
{cmd;cmd }	sh	Like (cmd;cmd ) without a subshell
>ofile	csh, sh	Standard output
>>ofile	csh, sh	Append to standard output
<ifile	csh, sh	Standard Input
<<word	csh, sh	Read until word, substitute variables
<<\word	csh, sh	Read until word, no substitution
<<-word	sh	Read until word, ignoring TABS
>>!file	csh	Append to file, ignore error if not there
>!file	csh	Output to new file, ignore error if not there
>&file	csh	Send standard & error output to file
<&digit	sh	Switch Standard Input to file
<&-	sh	Close Standard Input
>&digit	sh	Switch Standard Output to file
>&-	sh	Close Standard Output
digit1<&digit2	sh	Connect digit2 to digit1
digit<&-	sh	Close file digit
digit2>&digit1	sh	Connect digit2 to digit1
digit>&-	sh	Close file digit