Wednesday, October 28, 2009

Create a hash referece from two arrays using a hash slice.

Given http://www.perlmonks.org/?node_id=4402

and http://www.nntp.perl.org/group/perl.beginners/2009/03/msg106746.html

and the ouput of:


my $command = '/bin/rpm -qa "--queryformat=%{Name}\t%{Version}\t%{Arch}\t%{Epoch}\t%{Release}\n"';


...this works:


#
# Create a hash referece from two arrays using a hash slice.
#
my $pkg;
@{$pkg}{qw( name ver arch epoch rel )} = split(/\t/, $rpm_qa);


In case I need it again...

Tuesday, October 27, 2009

Scripting differences between ksh and bash

Test this:


#!/bin/bash

SET_VAR="didn't"
ls -l | while read LINE
do
SET_VAR="did"
done

echo "I $SET_VAR set var"


vs


#!/bin/ksh

SET_VAR="didn't"
ls -l | while read LINE
do
SET_VAR="did"
done

echo "I $SET_VAR set var"


bash seems to run the while in a sub shell, while ksh saves the pipeline up and runs it in its own instance.

Using:


while ...
do
...
done <<< "$(command)"


may help in bash.

Monday, October 26, 2009

Import a csv file into SQLite


#!/bin/bash

DIR=/tmp

rm $DIR/create.sql $DIR/load.sql $DIR/files.db

ls -l | sed 's/\s\s*/,/g' | tail -n +2 > $DIR/import.csv

cat < $DIR/load.sql
CREATE TABLE FILES(perms text,links int,user text,groups text,bytes int,mon text,day int,time_year text,file text);
.schema files
.separator ","
.import $DIR/import.csv FILES
.separator "\t"
select * from FILES;
.output $DIR/create.sql
.dump FILES
.output stdout
.backup main $DIR/files.db
.q
EOT

echo ".read $DIR/load.sql" | ./sqlite3


If you're working on an older version of sqlite3 that doesn't support .backup, you can create the database by running:


sqlite3 file.db


where file.db is a new file to create, then create the tables and import the data.


CREATE TABLE FILES(host text,perms text,links int,user text,groups text,bytes int,mon text,day int,time_year text,file text);
.schema files
.separator ";"
.import results.csv FILES
.separator "\t"
select * from FILES;
.output results.sql
.dump FILES
.output stdout
.q

git $PATH problems with ssh

If your git binaries are in a non-standard location you may have problems with the hard-coded path in sshd, which can mean any $PATH definitions in your remote .profile, .kshrc & .bashrc are ignored:


$ ssh host 'echo $PATH'
/usr/local/bin:/bin:/usr/bin
$ git clone ssh://host/$HOME/git/repo test
Initialized empty Git repository in /home/user/test/.git/
ksh: line 1: git-upload-pack: not found
fatal: The remote end hung up unexpectedly


This should work as a temporary fix:


git clone --upload-pack=git/bin/git-upload-pack ssh://host/$HOME/git/repo test

or

git clone -u git/bin/git-upload-pack ssh://localhost/$HOME/git/repo test

for short.

(where git/bin is the path to your git binaries at the remote end)

If you want to permanently set this once you've cloned it,
cd into the directory and issue the commands:


$ git config remote.origin.uploadpack git/bin/git-upload-pack
$ git config remote.origin.receivepack git/bin/git-receive-pack


These links may help:

Wednesday, October 21, 2009

bash 2.x prompt gotcha...

In my .bashrc I had:


PS1='\e]0;\u@\h:\w [`tty`]\a\u@\h:\w [`tty`]\n\$ '


On bash 2.x, this meant that every time I displayed my bash prompt it needed to run tty twice.

This had a nasty gotcha...


john@hostname:~ [/dev/pts/0]
$ bash --version ; echo "yes" | grep "no" ; echo $?
SunOS
GNU bash, version 2.03.0(1)-release (sparc-sun-solaris)
Copyright 1998 Free Software Foundation, Inc.
1
john@hostname:~ [/dev/pts/0]
$ echo "yes" | grep "no"
john@hostname:~ [/dev/pts/0]
$ echo $?
0


The echo $? on a line by itself was dutifully reporting the exit code of the last tty command executed in the PS1 variable!

Removing the commands from PS1 made the problem go away:


$ PS1="$ "
$ echo "yes" | grep "no" ; echo $?
1
$ echo "yes" | grep "no"
$ echo $?
1


It then behaves as expected...

(NB: I didn't seem to get the same problem in bash 3.x)

I have now changed my prompt to:


MYTTY=$(tty)
PS1='\e]0;\u@\h:\w [${MYTTY:5}]\a\u@\h:\w [${MYTTY:5}]\n\$ '

ssh-agent script

From: http://mah.everybody.org/docs/ssh



#!/bin/sh

SSH_ENV="$HOME/.ssh/environment.$HOSTNAME"

if [ -x /usr/bin/ssh-agent ]
then
SSH_AGENT=/usr/bin/ssh-agent
SSH_ADD=/usr/bin/ssh-add
else
echo "Can't find ssh-agent"
SSH_AGENT=/bin/false
SSH_ADD=/bin/false
fi

start_agent () {

printf "Starting new SSH agent... "
$SSH_AGENT > "${SSH_ENV}"
if [ $? = 0 ]
then
echo "OK"
printf "3s|^echo|#echo|\nw\n\q\n" | ed "${SSH_ENV}" >/dev/null 2>&1
chmod 600 "${SSH_ENV}"
. "${SSH_ENV}"
else
echo "ERROR"
fi
$SSH_ADD -l | grep : || {
$SSH_ADD;
}

}
#
# Source SSH settings, if there
#
if [ -f "${SSH_ENV}" ]; then
. "${SSH_ENV}"
#ps ${SSH_AGENT_PID} doesn't work under cywgin
ps -fu$LOGNAME | grep ${SSH_AGENT_PID}.*ssh-agent$ >/dev/null
if [ $? != 0 ]
then
start_agent;
else
$SSH_ADD -l | grep : || {
echo "Agent is running, but has no keys..."
$SSH_ADD
}
fi
else
start_agent;
fi


and add this to your .bashrc / .kshrc


alias ssh_agent='. $HOME/.ssh/ssh_agent'
SSH_ENV="$HOME/.ssh/environment.$HOSTNAME

Installing a local copy of git

# To build & install your own local copy of git:

wget -N http://kernel.org/pub/software/scm/git/git-1.6.5.1.tar.gz

# (link from http://git-scm.com/ )

tar xf git-1.6.5.1.tar.gz
cd git-1.6.5.1

#
# Turn off support for OpenSSL (used for IMAP over SSL)
# and curl (used for http: and https: repositories)
# These two seem to be broken on Red Hat
#
NO_OPENSSL=1
NO_CURL=1
export NO_OPENSSL
export NO_CURL

#
# You probably don't want to use the default of your home dir
# because it creates 5 dirs for git:
# $ ls ~/git
# bin lib lib64 libexec share
#
./configure --prefix=$HOME/git
make
make install

# then add $HOME/git/bin to $PATH

# Read this:
#
# http://www.kernel.org/pub/software/scm/git/docs/everyday.html
#
# And you should be sorted.

Wednesday, October 14, 2009

To export your PuTTY and WinSCP sessions

You can export your settings for these apps from regedit:

PuTTY:

HKEY_CURRENT_USER\Software\SimonTatham

WinSCP:

HKEY_CURRENT_USER\Software\Martin Prikryl

Tuesday, October 13, 2009

Copying and pasting in screen

When you're in screen and want to copy something...

Go
<Ctrl>-A [
Then move to where you want to mark, using your vi keys hjkl or the arrow keys.
Press
<Enter>
to set the first mark.
Select the block you want to copy by moving to the second mark
then press
<Enter>
to copy the selected text to the buffer

Then to use the selected text...

Say you want to cat it into a file...


$ cat > file


Then go
<Ctrl-A> ]
to paste.

This also lets you go back up into your scrollback.

http://www.samsarin.com/blog/2007/03/11/gnu-screen-working-with-the-scrollback-buffer/ is a good HOWTO for this.


$ cat ~/.screenrc
vbell_msg '*ding*'
vbell off
defscrollback 20000
scrollback 20000
compacthist on

Monday, October 12, 2009

protocol error: mtime.sec not delimited

If you get an error saying:


protocol error: mtime.sec not delimited


When you are using scp to send files to a machine...

Check the login process on that machine to see what messages are being echoed to STDOUT when you login.
If you can get rid of the message (e.g. by not running fortune or doing 'echo "blah"') then the error should go away.

If it's something you want to run on an interactive login, then you could put a test around it to only run it then...

e.g.


if [ $TERM == "xterm" ]; then
fortune -s
fi

Thursday, October 01, 2009

vi change on matching lines

If you'd like to do something globally on lines that match a string,
without needing to do anything to the string itself...

e.g. find all lines matching <img src=".*> and append </a>


:g/<img src=".*>/s%$%</a>%


This says:

globally match <img src=".*>

and on the matching lines substitute </a> for $