Difference between revisions of "Unix/Linux"

From dbawiki
Jump to: navigation, search
m (How can a shell script tell what directory it is in?)
m (How can a shell script find out what directory it is in?)
Line 678: Line 678:
 
===How can a shell script find out what directory it is in?===
 
===How can a shell script find out what directory it is in?===
 
<pre>
 
<pre>
DIR="$( cd "$( dirname "$0" )" && pwd )"
+
DIR="$(cd "$(dirname "$0")" && pwd)"
 
</pre>
 
</pre>
  

Revision as of 14:36, 29 April 2015

Contents

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

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

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

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

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 on a line with leader dots!

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'
}

Process command line arguments in shell

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

# ----------------------
# 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

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

Set terminal title from command line

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"

A decent Unix Prompt

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

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

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

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

What is todays 'Day Of the Year' number?

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

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.
In principle, there's nothing wrong with modifying the crontab file directly. You just lose the advantage of file locking 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.$$

Run a job from cron every Nth day of the month

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 -ef cuts off args cmd column on Solaris

On AIX, ps eww <PID> shows the full argument listing of a process (NOTE: no - sign!)
To see more than 80 characters of the last column on Solaris:

pargs <PID>

shows all the individual arguments to the command

/usr/ucb/ps auww

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

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
There are several methods but I think this is the easiest to remember

:g/^$/d

Right pad a variable

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

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)

Reset your password bypassing password rules

must be done as root

echo "user:new_password" | chpasswd

Sum the sizes of all files of an ls listing

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

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

How many processors on the machine?

  • 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

Use expect to respond automatically to interactive programs

#!/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"}

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

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

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
}

Kill all processes for a user

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

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

Use awk instead

awk 'BEGIN {FS="\n" RS="\n\n"} /search pattern/ { do something }' <file>
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

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

Different ways of Iteration in korn shell with a while loop

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?

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

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

Remove a directory/file containing weird control characters

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

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.

Return a list of Oracle databases running on a list of remote servers

#!/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

Neat way of checking whether SQL output needs sending to someone

#!/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

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]

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

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

Array processing

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

#!/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

#!/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

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

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 '

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

Use SSH config file

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

From grymoire.com

A decent korn/bash shell tutorial

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

trap

     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

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

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

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


Install rpmforge repository

  • 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

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

Checkout this file for global yum config

/etc/sysconfig/yum-cron-background

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.

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)

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

To change to static IP address (Redhat/CentOS)

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

sudo chkconfig httpd on
sudo chkconfig mysqld on

Run a command on lots of servers in parallel

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)

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

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

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

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!

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?

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

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