Tuesday, 2 June 2009

Resuming a large secure file copy with rsyc

rsync --partial --progress --rsh=ssh user@host:remote_file local_file

should resume the copy after scp dies in the ar$e


Tuesday, 19 May 2009

ssh keys

http://rcsg-gsir.imsb-dsgi.nrc-cnrc.gc.ca/documents/internet/node31.html

the target (ie the server you want to login to with out a password) needs the public key from the source host/user in the ~/.ssh/authorized_hosts file (or authorized_keys, depending on your os)

generate the public/private keys with ssh-keygen -t rsa

not really that hard, is it?

Tuesday, 14 April 2009

More bash shell tips and tricks

from http://billharlan.com/pub/papers/Bourne_shell_idioms.html

§    Text filtering commands



Administrating from scripts and the
command-line often benefit from pipes of text
filtering commands. Here are some that are
easy to overlook or forget.


  • mmencode converts to and from
    base64 and "quoted-printable" formats for email.
    Search for the metamail package.
    Unfortunately, this has become hard to find.


    Alternatively uuencode -m converts to base64,
    and uudecode -m converts from base64.


    Or decode and encode quoted-printable and
    base64 with

    perl -pe 'use MIME::QuotedPrint; $_=MIME::QuotedPrint::decode($_);'
    perl -pe 'use MIME::QuotedPrint; $_=MIME::QuotedPrint::encode($_);'
    perl -pe 'use MIME::Base64; $_=MIME::Base64::encode($_);'
    perl -pe 'use MIME::Base64; $_=MIME::Base64::decode($_);'


  • uniq lets you remove duplicated lines
    from a sorted file.
  • Count the number of times a given line
    occurs with
    sort | uniq -c | sort -n

  • Break one word per line with
    perl -pe 's/\s+/\n/g'


  • Combine separate lines into a single line
    of words with
    paste -s -d" " 

  • comm lets you suppress lines unique to
    one or both of two files.

  • cat -s never prints more than one blank
    line in a row.
  • Remove all blank lines with
    perl -ne 'print if /\S/'

  • Print lines starting with one containing
    FOO and ending with one containing BAR.
    sed -n '/FOO/,/BAR/p'


  • merge and diff3 for merging changes
    in files edited from a common ancestor.
  • fold breaks lines to proper width, and
    fmt will reformat lines into paragraphs.

  • dirname and basename let you
    extract the directory and filenames from a
    full path to a file.
  • namei breaks a pathname into pieces and
    follows symbolic links.
  • expand and col -x replace tabs by
    spaces.

  • col -b removes backspaces from a file.
  • cat -v shows non-printing characters as
    ascii escapes.
  • sed '1,10d' deletes the first 10
    lines.
  • sed -n '3p' and sed -n '3{p;q}'

    both print the third line, but the latter is
    more efficient.
  • sed '/foo/q' truncates a file after
    the line containing foo.
  • sed -ne '/foo/,/bar/p' prints
    everything from the line containing foo
    to the line containing bar.
  • Align space-delimited fields into orderly
    columns with column -t.

  • Right justify queries with
    printf "%40s" "Do you want to delete? [y/N] "

  • Convert dos text files to unix, and vice
    versa:
    dos2unix file.txt
    unix2dos file.txt
    tr -d \\r < win.txt > unix.txt # if you can't find dos2unix
    sed -e 's/$/\r/' < unix.txt > win.txt # if you can't find unix2dos


  • cat -n and nl numbers lines.
  • Both of these perform string substitution,
    but the latter allows more general regular
    expressions:
    sed -e 's/oldtext/newtext/g'
    perl -pe 's/oldtext/newtext/g'



    Here's how to replace double quotes by single
    quotes for TeX:

    < in.tex perl -pne 's%\B"\b%``%g' | 
    perl -pne "s%\b\"\B%''%g" > out.tex


  • Use iconv to convert between character
    encodings.
  • Here are two ways to find string patterns
    in a file:
    grep 'pattern' filename [file] [< file]
    perl -ne 'print if /pattern/' [file] [< file]


  • Print the first and third columns of each
    line:
    awk '{print $1,$3}'
    perl -alne 'print "$F[0] $F[2]"'

  • Convert to lower-case:
    tr '[A-Z]' '[a-z]'
    perl -pe 'tr/[A-Z]/[a-z]/'
    perl -pe '$_ =lc'


  • Simple character substitutions and
    deletions may be simplest with tr.
    tr -d '\n'  # delete newlines
    tr '\n' '\0' # replace newlines by null characters.

    $ echo 1-2a-3b | tr "[1-9]" "[2-9]" | tr '-' '_' | tr -d 'a'
    2_3_4b


  • You can pipe into a loop with read.
    Here is a complicated way to cat a text file,
    piping in and out of a loop.
    cat file | while read a; do echo "$a" ; done | cat

  • To read lines in pairs from two files try
    paste file1 file2 | while read a b ; do echo "$a $b" ; done


  • Sort a list of dependencies with tsort.
  • Reverse lines with tac and words with
    rev.



  • §    Files and directories




  • Select text (non-binary) files with
    one of these
    \ls | perl -lne 'print if -T'
    perl -le 'for (glob "*") {print if -T }'
    perl -le 'print for grep -T, <*>'


    The perl algorithm for detecting text files
    is very good.

  • To do something to files with goofy names,
    including spaces and dashes, delimit the
    files with null characters instead of
    whitespace or newlines.

    find -type f -print0 | xargs -r0 ls

  • See if a directory contains any accessible
    contents with
      if ls -A "${dir}"/* >& /dev/null ; then echo "has files" ; else echo "no files" ; fi
    [or]
    if [ "`ls -A ${dir}`" ] ; then echo "has files" ; else echo "no files" ; fi



    See if files of a certain type exist:

      if ls *.par >& /dev/null ; then echo "has par files" ; fi
    [or]
    ls *.par >& /dev/null && echo "has pars" || echo "no pars"


  • readlink -f will fully resolve what a
    symbolic link points to.


    Find all bad symbolic links with

    find . -type l |
    while read f ; do if ! readlink -f "$f" >&/dev/null
    then echo "$f" ; fi ; done




  • §    Variables



  • To see if a variable contains a regular
    expression, combine if and grep. For
    example to see if the name of a file begins
    with a dot, try
     if echo "$filename" | grep '^[.]' >/dev/null 
    then echo yes ; else echo no ; fi



    expr also has a support for limited
    regular expressions.

    if [ `expr "$filename" : '[.].*'` -ne 0 ] 
    then echo yes ; else echo no ; fi

  • Use read to avoid tokenizing filenames
    with spaces. Here's how to find all files
    containing a space, and replace them by
    underscores.

    find . -iname '*  *' | 
    while read f ; do
    echo mv "$f" "`echo "$f" | sed 's/ */_/g'`"
    done

  • For simple integer arithmetic use expr:
    N=`expr "$N" + 3`


  • For arbitrary-precision floating-point
    math, use bc -l
    # Get pi to 10 places with arctangent (bc man page)
    PI=`echo "scale=10; 4*a(1)" | bc -l`
    # Expensive calculation of zero (Craig Artley):
    ZERO=`echo "c($PI/4)-sqrt(2)/2" | bc -l`

  • seq 1 100 generates all integers
    between 1 and 100. To iterate a loop 100
    times, try
    for i in `seq 1 100` ; do ... ; done


  • You can set the environment of a subprocess
    by defining a variable on the same line. The
    current shell is not affected.
    $ x=doggie sh -c 'echo x=$x'
    x=doggie
    $ x=pig ; x=doggie echo x=$x
    x=pig

  • Test that a string has non-zero length with
    if [ -n "$string" ] ; then echo "not empty" ; fi



    The -n is actually the default for a
    string expression, so you can omit it:

    if [ "$string" ] ; then echo "not empty" ; fi


  • There are several good ways to set default
    values for environmental variables. Many do
    this
    if [ ! "$VARIABLE" ] ; then VARIABLE="default value" ; fi
    export VARIABLE


    A simple alternative is

    : ${VARIABLE:="default value"} 
    export VARIABLE



    The colon at the beginning of the line is
    necessary as a no-op that allows its
    arguments to be evaluated.

  • Rarely you may want to accept a variable
    defined as an empty string. If so, then omit
    the colon before the equals when setting the
    default.
    : ${VARIABLE="default value"} 
    export VARIABLE


    To test whether a string is defined, even if
    empty test

    if [ "${VARIABLE+x}" ] ; then echo DEFINED ; fi


  • To echo all variables starting with X:
    echo ${!X*}



  • §    Running commands



  • Use "$@" when passing command-line
    arguments unaltered to subprocesses. This is
    equivalent to passing "$1" "$2" ..., but
    the first version works properly for no
    arguments.

  • Test the processing of arguments, like this
    $ set a 'b c' d
    $ for i in "$@" ; do echo "|$i|" ; done
    |a|
    |b c|
    |d|
    $ for i in "$*" ; do echo "|$i|" ; done
    |a b c d|
    $ for i in $* ; do echo "|$i|" ; done
    |a|
    |b|
    |c|
    |d|

  • See what runtime options you may have set
    with set -o bind -p shopt -p and

    stty -a.


    For example, you can edit a bash by default
    in emacs mode. Change to vi with

    set -o vi


    In emacs mode, you can edit your command in
    your environmental $EDITOR with cntl-x
    cntl-e



    In vi-mode, use esc-v. See help fc
    for more.

  • Repeat the last argument of the previous
    command with !$. Repeat all arguments
    without the command with !*.
  • To guarantee that a background process
    outlives the current shell, add extra
    parentheses like this:
    ( command & )



    Otherwise, your current shell, by exiting X
    or ssh, may terminate all processes that have
    your shell as the parent process. The extra
    parentheses starts a subshell that exits as
    soon as the command is spawned in the
    background. The background process changes
    its parent process ID to 1. This is a
    command-line version of the "double fork."

  • Repeat until a command succeeds:
    while ! cvs -z 3 -q update -dPA ; do echo -n . ; sleep 60 ; done

  • Make a progress bar (loop while waiting on
    a process)

    sleep 10 & while ps -p $! >/dev/null; do echo -n . ; sleep 1 ; done ; echo 
    or
    while pidof mozilla-bin > /dev/null ; do echo -n . ; sleep 1 ; done ; echo


    pgrep -f or killall -0 are alternatives to pidof for this purpose.



  • §    Manipulating paths



  • Loop over the elements of a PATH by
    tokenizing with the character ':'.
    IFS=':' ; for dir in $PATH ; do echo $dir ; done


  • Check for the existence of an executable
    version of a command in your PATH:
    function checkPath() {IFS=':' ; for dir in $PATH ; do if [ -x "$dir/$1" ] ;
    then return 0; fi ; done; return 1;}
    if checkPath commandName ; then ... ; fi

  • Here is a lovely function to modify a PATH
    that I found in /etc/profile:
    pathmunge () {
    if ! echo $PATH | egrep "(^|:)$1($|:)" >/dev/null ; then
    if [ "$2" = "after" ] ; then
    PATH=$PATH:$1
    else
    PATH=$1:$PATH
    fi
    fi
    }




  • §    Common script chores



  • Debug the script with set -x.
  • Make a script exit immediately after any failed
    command with set -e.

  • Process flags in a script:
    for i in "$@" ; do
    case $i in
    -a) FLAG_A=1
    shift ;;
    -b) FLAG_B="$2"
    shift ; shift ;;
    --) shift ; break ;;
    esac
    done

  • Print help from a script:
    if [ $# -lt 1 -o "$1" = "-h" -o "$1" = "-help" -o "$1" = "--help" ] ; then
    cat <<-END
    Usage: `basename $0` [-flag] arg1 [arg2]
    More information.
    END
    exit
    fi


  • Handle errors with functions:


    Often an error exit is handled most cleanly
    with a function.

    print_usage_and_exit() {
    cat <<-END
    Usage: `basename $0` arg1 arg2 [arg3]
    The first two arguments are required.
    END
    exit
    }

    if [ $# -lt 2 ] ; then
    print_usage_and_exit
    fi


  • Here's a robust way to locate the directory
    containing a script, following symbolic
    links. (Taken from the launch script of
    FindBugs.)
    program="$0"
    while [ -h "$program" ]; do
    link=`ls -ld "$program"`
    link=`expr "$link" : '.*-> \(.*\)'`
    if [ "`expr "$link" : '/.*'`" = 0 ]; then
    dir=`dirname "$program"`
    program="$dir/$link"
    else
    program="$link"
    fi
    done
    script_directory=`dirname $program`
    script_directory=`cd $script_directory && /bin/pwd`

  • Trapping signals to stop scripts:


    Ever try to interrupt your script, then
    discover that it killed only one command and
    continued to the next? Force a complete exit
    by adding the following line early in your
    script.

    trap "exit 1" 1 2 3 15


    You can also trap normal and error exits:

    # force script to exit when any command fails
    set -e

    # Trap on any exit
    trap "echo Always called before exit" 0

    # Trap on error exit only
    trap "echo Error exit was called " ERR

    echo "Next command will fail"

    # Returns error code of 1
    false

    echo "Will not see this comment"


  • Process ID's


    Get the process ID of the current shell as
    $$, of the parent shell with $PPID
    and $! for the most recently backgrounded
    child process.


    Interactively, you get see child PID's
    with jobs -p.

  • Here's how to ask a yes or no question,
    with a default of no. It checks whether the
    first letter is a y or Y and ignores leading
    spaces.

    echo -n "Do you want to continue? [y/N]: "
    read answer
    if expr "$answer" : ' *[yY].*' > /dev/null; then
    echo Continuing
    else
    echo Quitting
    exit
    fi

  • Here's how to ask for a password without
    echoing the characters. The trapping ensures
    that an interrupt does not leave the echoing
    off.
    stty -echo
    trap "stty echo ; echo 'Interrupted' ; exit 1" 1 2 3 15
    echo -n "Enter password: "
    read password
    echo "Your password is \"$password\""
    stty echo



    Gnome and other frameworks often allow simple
    scripting of GUIs:

    password=`zenity --entry --text "Enter password:"`



  • §    File descriptors




  • Redirecting output file descriptors


    Here are common ways to capture the
    standard output and standard error
    of a single command in a log file:

    command >file.log 2>&1 
    command 2>&1 | tee file.log

  • If you have a script with many commands,
    you can have them all write to the same log
    file by default:

    # save default standard output in file descriptor 10
    exec 10>&1
    # redirect standard output to a log file.
    exec >file.log
    # redirect standard error to same log file
    exec 2>&1
    # close stdin
    exec 0<&-
    # This command will write to log file
    command
    # echo to default standard output instead of log file
    echo "Visible message" 1>&10


    Avoid file descriptor 5, which bash already
    uses. (ulimit -n should show many
    available file descriptors.)

  • Avoid writing to stdout if it is not connected to a terminal:
      test -t 1 && echo "Connected to a terminal"

  • Open a socket


    Associate a file descriptor, say 4, with a
    socket, and close with

    4< /dev/tcp/$hostname/$port
    4<&-


    A more portable solution is to use nc.
    Listen on a port with

    nc -l -p 3535



    Connect to a remote host port like

    echo 'GET /' | nc hostname 80


    An even more general utility is socat,
    which also handles Unix sockets.

  • Friday, 6 March 2009

    Perl - how to read in a file

    open(DF_FILE, "<$file");

    my @DF_CHECK = ;
    close(DF_FILE);
    unlink $file;

    print join("\n", @DF_CHECK) . "\n" if $DEBUG;

    LINE: foreach (@DF_CHECK)
    {

    next LINE if (/^$/ || /^Filesystem/); # skip the headings or blank lines

    print "line: " . $_ . "\n" if $DEBUG;

    my @line = split();
    my ($fs, $size, $user, $avail, $used_pct, $mount);


    if (@line eq 6) {
    ($fs, $size, $user, $avail, $used_pct, $mount) = @line;
    } elsif (@line eq 5) {
    $fs = $last_line;
    ($size, $user, $avail, $used_pct, $mount) = @line;
    } else {
    $used_pct = 0;
    }

    $used_pct =~ s/\%//g;
    if ($used_pct > $alert_limit ) {
    print "alert flag set\n" if $DEBUG;
    $alert_flag = "true";
    $message = $message . "\t" . $fs . ", used: " . $used_pct . "%, mount: " . $mount . "\r\n";
    }

    $last_line = $_;
    }

    if ($alert_flag eq "true" ) {
    return $message;
    }

    return undef;
    }

    Wednesday, 25 February 2009

    Subversion - how to undo a change

    Assume that revision 25 contains the changes we are undoing.

    In order to undo a commit that has been made to the repository we just tell SVN to apply the reverse of the changeset to our working copy in the current directory.

    svn merge --change -25 .

    easy.

    Friday, 16 January 2009

    Log4J properties file

    Conversion Patterns

    Below are some examples of conversion patterns.

    %d [%t] %-5p %c:%L %x - %m%n

    date [thread] p? class:line x? - message newline

    Similar to the TTCC layout except that the relative time is right padded if less than 6 digits, thread name is right padded if less than 15 characters and truncated if longer and the category name is left padded if shorter than 30 characters and truncated if longer.

    and the reference

    # Set root logger level to DEBUG and its only appender to A1.
    log4j.rootLogger=ERROR, CONSOLE

    # CONSOLE is set to be a ConsoleAppender.
    log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender

    # CONSOLE uses PatternLayout.
    log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
    log4j.appender.CONSOLE.layout.ConversionPattern=%d [%t] %-5p %c:%L %x - %m%n
    #log4j.appender.CONSOLE.layout.ConversionPattern=%d{ABSOLUTE} %5p %c:%L - %m%n


    # Print only messages of level WARN or above in the package com.foo.
    log4j.logger.com.hibernate=ERROR
    log4j.logger.org.apache.commons.httpclient=ERROR
    log4j.logger.org.apache.axis=INFO
    log4j.logger.com.brock=DEBUG

    Two Way SSL in WebLogic

    Here is a good article about setting up 2 way SSL in WLS, so I don't forget

    Two Way SSL

    Here is the JVM system property for outputting network debugging

    -Djavax.net.debug=all

    How to "ping" an SSL server

    openssl s_client -connect www.b2b-onramp2.openreach.co.uk:9443

    How to oveerride the keystore
    -Djavax.net.ssl.trustStore=c:/tmp/keystore.dat -Djavax.net.ssl.trustStorePassword=store12345