Moving from Subversion to Git

I have been using subversion for a number of years and it wasn’t until I had seen and sampled the simplicity and power of git that I decided once and for all to bite the bullet and migrate all my subversion repositories to git.

I’d done the same from cvs to subversion in the early 2000′s and still think the move worked out well with a bit of preparation.

An unfortunate side effect of subversion is that it takes a good bit of effort to set up and manage a new repository so I ended up with two somewhat monolithic repositories…

1. archives
2. projects

The ‘archives ‘ repository contained all old project work and the ‘projects’ one contained relevant or current project work.

The result of this was that each archive had a bundle of sub-folders, each containing a project in its’ own right. Although git can handle the concept of sub-modules it’s not the best way to structure your project. In fact, it was a pretty lazy to structure my subversion projects in the first place but convenience overcame system administrative chores at the time.

This article explains the following:

1. Converting a monolithic subversion repository to a git repository
2. Breaking out the new git repository into a set of discrete repositories.
3. General backup process and scripts to copy the new repositories across to a backup system.

First off, a couple of conventions I keep are…

My server stores a central set of repositories with the name of myproject.git
My workstations work with their local version of repositories called myproject (no .git)
My server exports it’s .git repositories to a backup server using the same .git naming convention.
I have created a git.git user.group on my server to run all git processes. File ownership is given to this user so other users can’t fowl things up at least without thinking about it first.

Step 1 – Migrating to subversion

I store all my git repositories on a server in the directory

/usr/local/share/gitrepos

All of my subversion repositories are stored in

/usr/local/share/svn

Even though each folder is accessible using standard paths and commands, I have to go through the subversion door using the same mechanism I would access it from a remote box, namely http://. Other people may use svn:// if that’s their way of working.

Migration is taken care of with a single command.

sudo git svn clone https://localhost/repository/projects --stdlayout --authors-file=/home/peter/authors.txt -t tags -b branches -T trunk /usr/local/share/gitrepos/projects.git/

An explanation of all the bits follow:

sudo – because I run everything as unprivileged user, sudo gives me the rights i need to create new files and folders.

git svn – this is the git subcommand that manages conversion of subversion repositories.

clone – make a copy of the repositories that I’m pointing at.

https://localhost/repository/projects – I access all my subversion repositories using secure http. This allows me to securely browse the content across the Internet and track things easily using Trac.

Depending on your setup, this parameter will contain the path to your svn repository,however you access it.

–stdlayout option tells git svn that my subversion repository is in the standard layout of trunk/branch/tags directories.

–authors file – this is a file I created by hand containing a list of all the people who committed project material in the past. It’d format is as follows:

peter= Peter Mac Giollafhearga <my email at mydomain.com>
simon= Simon Shagwell <simon\'s email at his domain.com>

-t tags -b branches -T trunk – these values are for completeness and I’m not sure they are necessary given the –stdlayout option, but if you’ve called your branches, tags and trunks anything different, this is how you find it.

Once the command has completed you should find a projects.git folder has been created and navigating into it you will see all your nasty subversion sub-folders which you should have set up as individual repositories in the first place…tut tut!

Step 2 – Breaking out Git into baby gits

The structure of the new git repository is something like this.

gitrepository/
  projects.git/
    project1/
    WorldDomination/
    SomeStuff/
    SomeotherStuff_V2/
    Demos/
    Downloads/
    .git/

The .git folder (you cans see it using ls -a) contains a list of all the git related material such as project history, revisions and tags.
Check you can see your history by typing

git log

The next task is to break the contents of the rather large ‘project’ folder into a git repository per project.
The tool for the job is a combination of the very useful git subtree command and a bit of custom shell scripting specific to this job.

The subtree functionality was written by Avery Pennarun and is hosted by the github site. You can download the git subtree command from the URL http://github.com/apenwarr/git-subtree. Installation instructions are on the same site so I won’t bore you with it here.

Once you have it installed you’re almost ready to roll. The following shell script has comments at the top to explain what it does. Save this to your favourite scripts folder and chmod it so it’s executable (chmod +x git_breakout.sh).

Then cd into the folder you created earlier (in my case /usr/local/share/gitrepository/projects). Run the script and watch the output. Depending on the size of your projects it will take a bit of time to complete; mine took about 20 minutes.

#!/bin/sh

#git_breakout.sh
#This script should be run from within a git repository folder that
#contains many child folders.
#It will create a branch for every subfolder it finds and a new
#top level folder for each.
#It then initialises a git respoitory, copying into the relevant branch

# Make sure only root can run our script
if [ "$(id -u)" != "0" ]; then
  echo "This script must be run as root" 1>&2
  exit 1
fi

current_dir=`echo ${PWD##*/}`
git_user=git
git_group=git

for project in $( ls . )
do
  if [ -d $project ]; then
    project_lower=`echo $project.git | tr [A-Z] [a-z]`
    branchname=$project_lower."export"
    echo "performing subtree split..."
    git subtree split -P $project -b $branchname
    mkdir ../$project_lower
    cd ../$project_lower
    echo "initialising git"
    git init
    echo "fetching branch"
    git fetch ../$current_dir $branchname
    git checkout -b master FETCH_HEAD 2>&1
    cd ..
    echo "setting appropriate ownership"
    chown $git_user.$git_group -R $project_lower
    cd $current_dir
  fi
done

Once the script has completed, you should be able to see a new directory structure, something along the following lines.

gitrepository/
  projects.git/
  project1.git
  worlddomination.git/
  somestuff.git/
  someotherstuff_v2.git/
  demos.git/
  downloads.git/

Each folder is now its’ own git repository with it’s own internal version history, tags, branches etc.
cd into one of the folders and do a git log just to confirm you still have history.

The original projects.git can be removed (after backing it up for safety’s sake) if you’re satisfied everything is in place. We’re now ready to proceed with the next stage of the game, namely backing up our new git repositories to a remote share.

Step 3 – Backing up Git

I use a 2TB removable disk as a central data server for sharing files throughout my network. My thinking is that should the place ever burn down and I have the opportunity, there’s only one box I need to grab before rushing out the door. Of course, I burn frequent snapshots of this box to DVD.

I have created a ‘backups’ share on the disk which I map to my physical server using NFS.

The entry in my /etc/fstab file is something like this.

192.168.0.20:/DataVolume/backups  /usr/local/share/backups  nfs defaults    0 0

This means I can read/write to my backups folder as if it was a local folder on a local disk.

The job at hand is to be able to backup my git repositories using a cron task scheduled to run when everything is nice and quiet. Below is the script I use to run my git backups.

#!/bin/bash
# git_backup.sh
# Backup git repositories to another folder
 
# Make sure only root can run our script
if [ "$(id -u)" != "0" ]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi

git_command=/usr/bin/git
#Where they're going to be backed up
backup_dir=/usr/local/share/backups/git
#Location of current live repositories
repository_dir=/usr/local/share/gitrepos

cd $repository_dir
for project in $( ls . )
do
    if [ -d $project ]; then
    destination="$backup_dir/$project"

    if [ -d $destination ]; then
      cd $destination
      echo "pulling $project..."
      $git_command pull
      echo "done."
      cd $repository_dir
    else
      echo "mkdir $destination"
      mkdir $destination
      cd "$repository_dir/$project"
      echo "cloning $project..."
      $git_command clone -v -l --no-hardlinks . $destination
      cd ..
      echo "done."
    fi
    fi
done

Once this script is run, you ‘ll have a copy of all your repositories in the backup folder. The next time it’s run should only take a fraction of the time as it won’t have to reestablish the git repository again.

So there you have it, migrating a subversion repository to git is really simple, the fun starts when you try to play with the results. I hope this has been helpful to others faced with the same job. Any improvements please let me know.

  • Share/Bookmark

Ubuntu 10.04 setup for Ruby on Rails and general use

This extract is from notes I took during the process of setting up both a desktop and laptop for general use as a development environment for Ruby on Rails (RoR) and PHP development.

There were lots of other steps (custom gems and environment stuff I like), but most of what follows is generic enough to get the basics in place. Happy Hacking!!

#Install Skype
sudo apt-get install libqt4-dbus libqt4-network libqt4-xml libasound2
sudo dpkg -i skype-ubuntu-intrepid_2.1.0.81-1_amd64.deb

#Install Amarok
sudo apt-get install xine-ui libxine1-ffmpeg

##
#To get remote shares mapping in fstab
##

#install the smb client package
sudo aptitude install smbfs

sudo apt-get install portmap nfs-common

#Add the following line to /etc/hosts.deny:
echo portmap : ALL>>/etc/hosts.deny

#By blocking all clients first, only clients in /etc/hosts.allow below
#will be allowed to access the server.

#Now add the following line to /etc/hosts.allow:
echo portmap : NFS server IP address>>hosts.allow

sudo mkdir /mnt/
…etc
sudo mkdir /mnt/music
…etc
sudo mkdir /mnt/backups

Create a file in home folder called .smbcredentials (note the leading dot)
touch ~/.smbcredentials
echo username=
echo password=
chmod 600 smbcredentials

Now an entry in /etc/fstab
#Added a permanent share to shares on NAS box
#Note: everything that follows (up to the 0 0 should appear on the one line)
#and one line is required for each share you want to map

//192.168.0.20/ /mnt/ cifs
uid=peter,credentials=/home/peter/.smbcredentials,domain=office,dir_mode=0777,file_mode=0777 0 0

#setup filezilla
sudo aptitude install filezilla

#Limewire – download LimeWireLinux.deb from limewire site
# reports missing dependencies
peter@enspire:~/Downloads$ sudo dpkg -i LimeWireLinux.deb
limewire-basic depends on sun-java6-jre | icedtea-java7-jre |
sun-java6-jdk | icedtea-java7-jdk; however:
Package sun-java6-jre is not installed.
Package icedtea-java7-jre is not installed.
Package sun-java6-jdk is not installed.
Package icedtea-java7-jdk is not installed.
dpkg: error processing limewire-basic (–install):
dependency problems – leaving unconfigured

#Open synaptic package manager.
#Go to the Settings/Repositories/Other sources tab.
#Check the two default partner sites.

#Reload the package list and select the following
#sun-java6-jre
#sun-java6-plugin
#sun-java6-fonts packages

##
# Installing ruby and associated gems
##

sudo apt-get install ruby

sudo apt-get install rubygems

sudo gem install rake
sudo gem install rails

#tried to install capistrano using sudo but it wasn’t working on laptop
#however it did work on desktop
#sudo gem install capistrano
# or without sudo…
#gem install capistrano

#changed ~/.bashrc to include path to new gems
#Added PMGF 2010-06-24
export PATH=$PATH:~/.gem/ruby/1.8/bin:/var/lib/gems/1.8/bin

###
# Now install and configure mysql before trying to install any of the ruby mysql gems
###

#install mysql server
sudo apt-get install mysql-server
#setup prompts you for a password – enter it, remember it and enter it again.

#install the mysql admin tools
sudo apt-get install mysql-admin

#NB – must install the libmysqlclient[nn]-dev package
# this has mysql_config bundled with it which is needed by the ruby gems

#execute the following to find out what version of libmysqlclient yo’re running

dpkg –get-selections | grep mysqlclient

#in my case it’s version 16, so execute the following

sudo apt-get install libmysqlclient16-dev

#Next, you NEED TO INSTALL the ruby1.8 dev package
#If you don’t you’ll get all sorts of mysql gem errors — frustrating!!!
sudo apt-get install ruby1.8-dev

#now go for the mysql gem
sudo gem install mysql

###
# Installing and configuring git
###

sudo apt-get install git-core
git config –global user.email

###
# Installing apache
###
sudo apt-get install apache2
#the line above should do it, if you get any glitches, try the following
#sudo apt-get install apache2.2-bin
#sudo apt-get install apache2.2-common
#sudo apt-get install apache2-threaded-dev

###
# Installing php
###
sudo apt-get install php5
sudo apt-get install php5-mysql

  • Share/Bookmark

Linux Command Line Tips

This list of commands is pretty much a copy found on Pádraig Brady’s site PixelBeat. It’s reproduced here for personal convenience.

Note:The commands with the • in the left hand column are safe to copy and paste as is.

Command Description
apropos whatis Show commands pertinent to string.
man -t man | ps2pdf – > man.pdf make a pdf of a manual page
which command Show full path name of command
time command See how long a command takes
time cat Start stopwatch. Ctrl-d to stop.
dir navigation
cd - Go to previous directory
cd Go to $HOME directory
(cd dir && command) Go to dir, execute command and return to current dir
pushd . Put current dir on stack so you can popd back to it
alias l=’ls -l –color=auto’ quick dir listing
ls -lrt List files by date.
ls /usr/bin | pr -T9 -W$COLUMNS Print in 9 columns to width of terminal
find -name ‘*.[ch]‘ | xargs grep -E ‘expr’ Search ‘expr’ in this dir and below.
find -type f -print0 | xargs -r0 grep -F ‘example’ Search all regular files for ‘example’ in this dir and below
find -maxdepth 1 -type f | xargs grep -F ‘example’ Search all regular files for ‘example’ in this dir
find -type f ! -perm -444 Find files not readable by all (useful for web site)
find -type d ! -perm -111 Find dirs not accessible by all (useful for web site)
locate -r ‘file[^/]*\.txt’ Search cached index for names. This re is like glob *file*.txt
look reference Quickly search (sorted) dictionary for prefix
grep –color reference /usr/share/dict/words Highlight occurances of regular expression in dictionary
archives and compression
gpg -c file Encrypt file
gpg file.gpg Decrypt file
tar -c dir/ | bzip2 > dir.tar.bz2 Make compressed archive of dir/
bzip2 -dc dir.tar.bz2 | tar -x Extract archive (use gzip instead of bzip2 for tar.gz files)
tar -c dir/ | gzip | gpg -c | ssh user@remote ‘dd of=dir.tar.gz.gpg’ Make encrypted archive of dir/ on remote machine
find dir/ -name ‘*.txt’ | tar -c –files-from=- | bzip2 > dir_txt.tar.bz2 Make archive of subset of dir/ and below
find dir/ -name ‘*.txt’ | xargs cp -a –target-directory=dir_txt/ –parents Make copy of subset of dir/ and below
( tar -c /dir/to/copy ) | ( cd /where/to/ && tar -x -p ) Copy (with permissions) copy/ dir to /where/to/ dir
( cd /dir/to/copy && tar -c . ) | ( cd /where/to/ && tar -x -p ) Copy (with permissions) contents of copy/ dir to /where/to/
( tar -c /dir/to/copy ) | ssh -C user@remote ‘cd /where/to/ && tar -x -p’ Copy (with permissions) copy/ dir to remote:/where/to/ dir
dd bs=1M if=/dev/sda | gzip | ssh user@remote ‘dd of=sda.gz’ Backup harddisk to remote machine
rsync (Network efficient file copier: Use the –dry-run option for testing)
rsync -P rsync://rsync.server.com/path/to/file file Only get diffs. Do multiple times for troublesome downloads
rsync –bwlimit=1000 fromfile tofile Locally copy with rate limit. It’s like nice for I/O
rsync -az -e ssh –delete ~/public_html/ remote.com:’~/public_html’ Mirror web site (using compression and encryption)
rsync -auz -e ssh remote:/dir/ . && rsync -auz -e ssh . remote:/dir/ Synchronize current directory with remote one
ssh (Secure SHell)
ssh $USER@$HOST command Run command on $HOST as $USER (default command=shell)
ssh -f -Y $USER@$HOSTNAME xeyes Run GUI command on $HOSTNAME as $USER
scp -p -r $USER@$HOST: file dir/ Copy with permissions to $USER’s home directory on $HOST
ssh -g -L 8080:localhost:80 root@$HOST Forward connections to $HOSTNAME:8080 out to $HOST:80
ssh -R 1434:imap:143 root@$HOST Forward connections from $HOST:1434 in to imap:143
ssh-copy-id $USER@$HOST Install $USER’s public key on $HOST for password-less log in
wget (multi purpose download tool)
(cd dir/ && wget -nd -pHEKk http://www.pixelbeat.org/cmdline.html) Store local browsable version of a page to the current dir
wget -c http://www.example.com/large.file Continue downloading a partially downloaded file
wget -r -nd -np -l1 -A ‘*.jpg’ http://www.example.com/dir/ Download a set of files to the current directory
wget ftp://remote/file[1-9].iso/ FTP supports globbing directly
wget -q -O- http://www.pixelbeat.org/timeline.html | grep ‘a href’ | head Process output directly
echo ‘wget url’ | at 01:00 Download url at 1AM to current dir
wget –limit-rate=20k url Do a low priority download (limit to 20KB/s in this case)
wget -nv –spider –force-html -i bookmarks.html Check links in a file
wget –mirror http://www.example.com/ Efficiently update a local copy of a site (handy from cron)
networking (Note ifconfig, route, mii-tool, nslookup commands are obsolete)
ethtool eth0 Show status of ethernet interface eth0
ethtool –change eth0 autoneg off speed 100 duplex full Manually set ethernet interface speed
iwconfig eth1 Show status of wireless interface eth1
iwconfig eth1 rate 1Mb/s fixed Manually set wireless interface speed
iwlist scan List wireless networks in range
ip link show List network interfaces
ip link set dev eth0 name wan Rename interface eth0 to wan
ip link set dev eth0 up Bring interface eth0 up (or down)
ip addr show List addresses for interfaces
ip addr add 1.2.3.4/24 brd + dev eth0 Add (or del) ip and mask (255.255.255.0)
ip route show List routing table
ip route add default via 1.2.3.254 Set default gateway to 1.2.3.254
host pixelbeat.org Lookup DNS ip address for name or vice versa
hostname -i Lookup local ip address (equivalent to host `hostname`)
whois pixelbeat.org Lookup whois info for hostname or ip address
netstat -tupl List internet services on a system
netstat -tup List active connections to/from system
windows networking (Note samba is the package that provides all this windows specific networking support)
smbtree Find windows machines. See also findsmb
nmblookup -A 1.2.3.4 Find the windows (netbios) name associated with ip address
smbclient -L windows_box List shares on windows machine or samba server
mount -t smbfs -o fmask=666,guest //windows_box/share /mnt/share Mount a windows share
echo ‘message’ | smbclient -M windows_box Send popup to windows machine (off by default in XP sp2)
text manipulation (Note sed uses stdin and stdout. Newer versions support inplace editing with the -i option)
sed ‘s/string1/string2/g’ Replace string1 with string2
sed ‘s/\(.*\)1/\12/g’ Modify anystring1 to anystring2
sed ‘/ *#/d; /^ *$/d’ Remove comments and blank lines
sed ‘:a; /\\$/N; s/\\\n//; ta’ Concatenate lines with trailing \
sed ‘s/[ \t]*$//’ Remove trailing spaces from lines
sed ‘s/\([`"$\]\)/\\\1/g’ Escape shell metacharacters active within double quotes
seq 10 | sed “s/^/      /; s/ *\(.\{7,\}\)/\1/” Right align numbers
sed -n ’1000{p;q}’ Print 1000th line
sed -n ’10,20p;20q Print lines 10 to 20
sed -n ‘s/.*<title>\(.*\)<\/title>.*/\1/ip;T;q Extract title from HTML web page
sed -i 42d ~/.ssh/known_hosts Delete a particular line
sort -t. -k1,1n -k2,2n -k3,3n -k4,4n Sort IPV4 ip addresses
echo ‘Test’ | tr ‘[:lower:]‘ ‘[:upper:]‘ Case conversion
tr -dc ‘[:print:]‘ < /dev/urandom Filter non printable characters
tr -s ‘[:blank:]‘ ‘\t’ </proc/diskstats | cut -f4 cut fields separated by blanks
history | wc -l Count lines
set operations (Note you can export LANG=C for speed. Also these assume no duplicate lines within a file)
sort file1 file2 | uniq Union of unsorted files
sort file1 file2 | uniq -d Intersection of unsorted files
sort file1 file1 file2 | uniq -u Difference of unsorted files
sort file1 file2 | uniq -u Symmetric Difference of unsorted files
join -t’\0′ -a1 -a2 file1 file2 Union of sorted files
join -t’\0′ file1 file2 Intersection of sorted files
join -t’\0′ -v2 file1 file2 Difference of sorted files
join -t’\0′ -v1 -v2 file1 file2 Symmetric Difference of sorted files
math
echo ‘(1 + sqrt(5))/2′ | bc -l Quick math (Calculate φ).
echo ‘pad=20; min=64; (100*10^6)/((pad+min)*8)’ | bc More complex (int) e.g. This shows max FastE packet rate
echo ‘pad=20; min=64; print (100E6)/((pad+min)*8)’ | python Python handles scientific notation
echo ‘pad=20; plot [64:1518] (100*10**6)/((pad+x)*8)’ | gnuplot -persist Plot FastE packet rate vs packet size
echo ‘obase=16; ibase=10; 64206′ | bc Base conversion (decimal to hexadecimal)
echo $((0x2dec)) Base conversion (hex to dec) ((shell arithmetic expansion))
units -t ’100m/s’ ‘miles/hour’ Unit conversion (metric to imperial)
units -t ’500GB’ ‘GiB’ Unit conversion (SI to IEC prefixes)
units -t ’1 googol’ Definition lookup
seq 100 | (tr ‘\n’ +; echo 0) | bc Add a column of numbers.
calendar
cal -3 Display a calendar
cal 9 1752 Display a calendar for a particular month year
date -d fri What date is it this friday.
[ $(date -d "tomorrow" +%d) = "01" ] || exit exit a script unless it’s the last day of the month
date –date=’25 Dec’ +%A What day does xmas fall on, this year
date –date=’@2147483647′ Convert seconds since the epoch (1970-01-01 UTC) to date
TZ=’America/Los_Angeles’ date What time is it on west coast of US (use tzselect to find TZ)
date –date=’TZ=”America/Los_Angeles” 09:00 next Fri’ What’s the local time for 9AM next Friday on west coast US
locales
printf “%’d\n” 1234 Print number with thousands grouping appropriate to locale
BLOCK_SIZE=\’1 ls -l Use locale thousands grouping in ls.
echo “I live in `locale territory`” Extract info from locale database
LANG=en_IE.utf8 locale int_prefix Lookup locale info for specific country.
locale | cut -d= -f1 | xargs locale -kc | less List fields available in locale database
recode (Obsoletes iconv, dos2unix, unix2dos)
recode -l | less Show available conversions (aliases on each line)
recode windows-1252.. file_to_change.txt Windows “ansi” to local charset (auto does CRLF conversion)
recode utf-8/CRLF.. file_to_change.txt Windows utf8 to local charset
recode iso-8859-15..utf8 file_to_change.txt Latin9 (western europe) to utf8
recode ../b64 < file.txt > file.b64 Base64 encode
recode /qp.. < file.qp > file.txt Quoted printable decode
recode ..HTML < file.txt > file.html Text to HTML
recode -lf windows-1252 | grep euro Lookup table of characters
echo -n 0×80 | recode latin-9/x1..dump Show what a code represents in latin-9 charmap
echo -n 0x20AC | recode ucs-2/x2..latin-9/x Show latin-9 encoding
echo -n 0x20AC | recode ucs-2/x2..utf-8/x Show utf-8 encoding
CDs
gzip < /dev/cdrom > cdrom.iso.gz Save copy of data cdrom
mkisofs -V LABEL -r dir | gzip > cdrom.iso.gz Create cdrom image from contents of dir
mount -o loop cdrom.iso /mnt/dir Mount the cdrom image at /mnt/dir (read only)
cdrecord -v dev=/dev/cdrom blank=fast Clear a CDRW
gzip -dc cdrom.iso.gz | cdrecord -v dev=/dev/cdrom - Burn cdrom image (use dev=ATAPI -scanbus to confirm dev)
cdparanoia -B Rip audio tracks from CD to wav files in current dir
cdrecord -v dev=/dev/cdrom -audio -pad *.wav Make audio CD from all wavs in current dir (see also cdrdao)
oggenc –tracknum=’track’ track.cdda.wav -o ‘track.ogg’ Make ogg file from wav file
disk space
ls -lSr Show files by size, biggest last
du -s * | sort -k1,1rn | head Show top disk users in current dir.
du -hs /home/* | sort -k1,1h Sort paths by easy to interpret disk usage
df -h Show free space on mounted filesystems
df -i Show free inodes on mounted filesystems
fdisk -l Show disks partitions sizes and types (run as root)
rpm -q -a –qf ‘%10{SIZE}\t%{NAME}\n’ | sort -k1,1n List all packages by installed size (Bytes) on rpm distros
dpkg -query -W -f=’${Installed-Size;10}\t${Package}\n’ | sort -k1,1n List all packages by installed size (KBytes) on deb distros
dd bs=1 seek=2TB if=/dev/null of=ext3.test Create a large test file (taking no space).
> file truncate data of file or create an empty file
monitoring/debugging
tail -f /var/log/messages Monitor messages in a log file
strace -c ls >/dev/null Summarise/profile system calls made by command
strace -f -e open ls >/dev/null List system calls made by command
ltrace -f -e getenv ls >/dev/null List library calls made by command
lsof -p $$ List paths that process id has open
lsof ~ List processes that have specified path open
tcpdump not port 22 Show network traffic except ssh.
ps -e -o pid,args –forest List processes in a hierarchy
ps -e -o pcpu,cpu,nice,state,cputime,args –sort pcpu | sed ‘/^ 0.0 /d’ List processes by % cpu usage
ps -e -orss=,args= | sort -b -k1,1n | pr -TW$COLUMNS List processes by mem (KB) usage.
ps -C firefox-bin -L -o pid,tid,pcpu,state List all threads for a particular process
ps -p 1,2 List info for particular process IDs
last reboot Show system reboot history
free -m Show amount of (remaining) RAM (-m displays in MB)
watch -n.1 ‘cat /proc/interrupts’ Watch changeable data continuously
udevadm monitor Monitor udev events to help configure rules
system information
uname -a Show kernel version and system architecture
head -n1 /etc/issue Show name and version of distribution
cat /proc/partitions Show all partitions registered on the system
grep MemTotal /proc/meminfo Show RAM total seen by the system
grep “model name” /proc/cpuinfo Show CPU(s) info
lspci -tv Show PCI info
lsusb -tv Show USB info
mount | column -t List mounted filesystems on the system (and align output)
grep -F capacity: /proc/acpi/battery/BAT0/info Show state of cells in laptop battery
# dmidecode -q | less Display SMBIOS/DMI information
# smartctl -A /dev/sda | grep Power_On_Hours How long has this disk (system) been powered on in total
# hdparm -i /dev/sda Show info about disk sda
# hdparm -tT /dev/sda Do a read speed test on disk sda
# badblocks -s /dev/sda Test for unreadable blocks on disk sda
interactive
readline Line editor used by bash, python, bc, gnuplot, …
screen Virtual terminals with detach capability, …
mc Powerful file manager that can browse rpm, tar, ftp, ssh, …
gnuplot Interactive/scriptable graphing
links Web browser
xdg-open . open a file or url with the registered desktop application
  • Share/Bookmark

ClamAV – Antivirus Scanner on Fedora8

I’ve just spent the best part of two hours fighting with the set-up of clamav on a relatively new Fedora 8 Server.  The documentation wasn’t the greatest so I’ve decided to do my bit to patch some of the holes.

Download clam

# sudo yum clamav clamav-server clamav-update

A number of instances of the clamd daemon can run concurrently. Each instance needs to be provided with a unique name. To keep things simple, we’re going to run one instance and call it ‘server’. This name has implications for what is to follow.
Setting up the daemon up as running service involves the following steps:

Phase 1 – create a daemon user

When you install clamav using the yum utility, a new user is created automatically – The user is clamav. Most documentation uses this user as the daemon user – this isn’t a good idea. The clamav user has rights to update the database containig the list of known virii.   Create a new user clamd with no login rights.

#sudo useradd -s /sbin/nologin/ clamd

Phase 2 – Copying and renaming config files

Copy assorted files from /usr/share/doc/clamav-server-nn.nn.nn/ (where nn is the version number of your install) to assorted folders, renaming them and modifying their content.

# cp /usr/share/doc/clam-server-nn.nn.nn/clamd.conf /etc/clamd.d/
# cp /usr/share/doc/clam-server-nn.nn.nn/clamd.sysconfig /etc/sysconfig/clamd.server
# cp /usr/share/doc/clam-server-nn.nn.nn/clamd.logrotate /etc/logrotate.d/clamd

Phase 3 – Editing the configuration files

Start by editing the /etc/clamd.d/clamd.conf file.

Firstly, comment out the line saying Example in file clamd.conf

 LogFile /var/log/clamd/clamd.log
Edit the LogSysLog setting LogSysLog yes
PidFile /var/run/clamd.server/clamd.pid
LocalSocket /var/run/clamd.server/clamd.sock
TcpAddr 127.0.0.1
User clamd

Phase 3 – Create the folders

Create the /var/run/clamd.server folder

#mkdir /var/run/clamd.server
#chown clamd.clamd /var/run/clamd.server

Create the clamd log folder

 #mkdir /var/log/clamd
#touch /var/log/clamd/clamd.log
#chown clamd.clamd -R /var/log/clamd/
#chmod 0620 /var/log/clamd/clamd.log

Copy the clamd-wrapper to clamd.server

# cp /etc/init.d/clamd-wrapper /etc/init.d/clamd.server

Edit the CLAMD_SERVICE variable in the /etc/init.d/clamd.server file

CLAMD_SERVICE=server

Geez..this is getting complicated…one final step

Create a clamd.server file in /usr/sbin that links to the original clamd file

# ln -s /usr/sbin/clamd.server /usr/sbin/clamd

OK..all systems go…

now start the daemon

#etc/init.d/clamd.server start

If you want the daemon to start on reboot add it to the startup list using chkconfig

# /sbin/chkconfig clamd.server start

Hopefully you get the green light and have a running clamd daemon. If you don’t (check using ps auxw | grep clamd) please post a comment and let me know what grief you’re having.

  • Share/Bookmark