Wednesday 28 September 2011

Initrd modification and explanation

Recently I had to change the initrd file accordingly for booting customised xen vm installtion. I did some research and found the following steps with which I've edited the init file inside initrd to point to the right harddrive ::

mkdir ~/tmp
cd ~/tmp
cp /boot/initrd.img ./initrd.gz
gunzip initrd.gz
mkdir tmp2
cd tmp2
cpio -id < ../initrd.img

now you should have a lot of files in ~/tmp/tmp2 directories, including a lot of subdirectories like sbin,lib

now do the required changes to the files
then pack the files back into the archive using the following command
cd ~/tmp/tmp2

find . | cpio --create --format='newc' > ~/tmp/newinitrd
cd ~/tmp
gzip newinitrd

now you would have a newinitrd.gz
rename this now -
mv newinitrd.gz as newinitrd.img
this is the new boot image now !!

Following is much detailed explanation.

 

Introduction

Ever wondered what’s inside of the initrd file? This article tells you how to look into the initrd and even modify it.

Few words about initrd

Linux uses the initrd or initial ram-disk during the boot process. Linux kernel is very modular as you know. While the kernel main file contains only the most needed stuff, rest of the kernel, drivers included, reside in separate files – the kernel modules.
It would be impossible to create a single kernel binary image that would suit all the hardware configurations out there. Instead, kernel supports the initrd. initrd is a virtual file-system that contains drivers (kernel modules) needed to boot the system. For instance, very often a SCSI controllers drivers reside inside of the initrd. Kernel needs a SCSI controller driver to boot the operating system, but it does not include it, nor it can read it from hard-disk (you’d need a driver for the hard-disk, right?). And this is when the initrd becomes very handy.
BIOS routines that read the actual kernel from the disk into RAM, do the same job with initrd. When Linux kernel boots, long before trying to mount the real root file-system, it loads initrd into memory and makes it a temporary root file-system.
See how handy this is. initrd itself requires no drivers whatsoever, because BIOS handles all the work of loading it into memory. On the other hand, it contains all the drivers Linux needs to boot. And you can easily rebuild it without changing the kernel.
After loading initrd into RAM, the kernel runs a script named init that resides in initrd‘s root directory. The script contains commands that would load all required kernel modules. And only after that Linux tries to mount the real root file-system.

Few words about history

Content of the initrd file and its format has significantly changed over last couple of years. Something like four years ago, it was a common practice to create a real RAM-disk with a fixed size, format it with ext2 file-system and write some data to it.
To look into it, you had to open it up with gzip and then mount using loopback device (mount -o loop).
Today things are totally different. Kernel configuration option that configures the size of initrd has gone. It wasn’t really convenient because your system was limited to certain initrd size. Instead kernel adapts itself to initrd, no matter what is it’s size.

Back to the real thing

Like the kernel, initrd is compressed to save disk space. Unlike the kernel, it can be easily decompressed. The tool we’ll use to decompress it is, nothing fancy gzip. Same good old gzip that we use so often.
Now before we begin it is a good idea to create a directory where we’ll work. After all, internal structure of initrd is quiet complex and we don’t want to mix contents the initrd with contents of your, let’s say, home directory. So, do mkdir and cd to create our clean environment. We’ll call this directory A. To make things even cleaner, place initrd file into your newly created directory and an additional directory in it. This is directory B. In that directory we will have the contents of the initrd. Eventually, you should have a layout similar to this one.
Let’s start decompressing. Enter directory A and copy initrd that you would like to open into the directory. Then, rename it so that it would have .gz extension. The thing is that initrd is gzip compressed archive. Since gzip refuses do decompress something that doesn’t have .gz extension, we have to rename the file.
Next we have to decompress the file. gzip -d does the job for us. Next step is to open up the cpio archive. Yes, modern initrd is a cpio archive. We can do that with cpio -i < , but before we do that, we have to enter directory B specifying file name with double dots indicating file is in the parent directory – the A directory.
01sasha@sasha-linux:~/A$ cp /boot/initrd.img-2.6.24-16-generic .
02sasha@sasha-linux:~/A$ mv initrd.img-2.6.24-16-generic initrd.img-2.6.24-16-generi
03c.gz
04sasha@sasha-linux:~/A$ gzip -d initrd.img-2.6.24-16-generic.gz
05sasha@sasha-linux:~/A$ ls
06B/  initrd.img-2.6.24-16-generic
07sasha@sasha-linux:~/A$ cd B/
08sasha@sasha-linux:~/A/B$ cpio -i < ../initrd.img-2.6.24-16-generic
0942155 blocks
10sasha@sasha-linux:~/A/B$ ls -F
11bin/  conf/  etc/  init*  lib/  modules/  sbin/  scripts/  usr/  var/
12sasha@sasha-linux:~/A/B$
In this example you can see me opening default initial ram-disk image from my Ubuntu 8.04 installation. We can see that the initrd opened up into a nice directory tree that resembles your root directory structure. In the heart of the initrd structure is the init script that does most of the job of loading right modules when system boots.
The content of the init script is different from distribution to distribution. The main difference is in approach. In some distributions developers preferred to keep as many initializations as possible out of the initrd. In other distributions developers didn’t care that much about keeping initrd small and fast. In general both approaches has a place under the sun. First approach based on the fact that initrd is a limited environment, on the contrary to Linux when its fully loaded. Thus when Linux is fully loaded, you can do more complex stuff with less effort. Second approach on the other hand, sees in initrd an environment that works faster than “big” Linux, so it uses initrd‘s fastness to do some initializations.
Ubuntu’s initrd image based upon first approach. It uses a shell program named busybox – the shell environment originally designed for embedded systems and known for its small memory footprint and good performance. initrd in OpenSuSE 10.2 on the other hand uses bash shell – same shell as you use regularly. This is a clear example of the second approach.
Another interesting input to look at, is the fact that init script in Ubuntu 8.04 is ~200 lines long, while in OpenSuSE 10.2 it is ~1000 lines long.

Changing it

Once you have it opened up, you can see things inside of it and even make some modifications. As I already explained, structure of the initial ram-disk changes from distribution to distribution.  However, all distributions share few common things. For instance, disregarding the distribution and a particular initrd format, lib/modules/ directory always contains kernel modules that initrd loads at boot time. You may swap one module with another without anyone even noticing.
Number of modules, their names, etc controlled via init script in distribution dependent form. Therefore, no matter what distribution of Linux you have, init script is the key to understanding how initrd works. Apprehend the init script, and you will have full control over your initrd, it’s contents and what it does.

Packing it back

Assuming you’re done playing around with initrd contents and you want to pack it back. Here is what you do.
First you have to pack cpio archive. Remember the B directory we’ve created. This is where it becomes handy. We want to keep contents of the initrd as clean as possible. The A-B separation allows us to keep the original initrd image out of the way when packing it back.
This is how we do that. First, we should enter the B directory. From there, run following command:
1find | cpio -H newc -o > ../new_initrd_file
This will create a new initrd file named new_initrd_file inside of directory A.
Next enter directory A and pack the cpio archive with gzip. Here’s the command that should do the job.
1gzip -9 new_initrd_file
This will pack the initrd in new_initrd_file into new_initrd_file.gz archive. Finally rename the file into whatever you want to call it. Remember that getting rid of .gz extension is a common practice, although not a necessity.
This is how complete session will look like on Ubuntu:
01sasha@sasha-linux:~$ cd A/B/
02sasha@sasha-linux:~/A/B$ find | cpio -H newc -o > ../new_initrd_image
0342155 blocks
04sasha@sasha-linux:~/A/B$ cd ../
05sasha@sasha-linux:~/A$ gzip -9 new_initrd_image
06sasha@sasha-linux:~/A$ ls
07B  initrd.img-2.6.24-16-generic  new_initrd_image.gz
08sasha@sasha-linux:~/A$ mv new_initrd_image.gz initrd.img-2.6.24-16-generic-modified
09sasha@sasha-linux:~/A$ ls
10B  initrd.img-2.6.24-16-generic  initrd.img-2.6.24-16-generic-modified
11sasha@sasha-linux:~/A$

Booting with the new initrd

Changing initrd is always a risky business. When playing with matters of this kind, mistakes are common and it is important to stay on the safe side. Adding a new GRUB configuration is not such a big deal, but by all means do so when trying to boot the brewed five minutes ago initrd. You’ll save yourself lots of time reinstalling distributions and poking around with different rescue systems to make your system boot again.
Have fun!

References:

Friday 23 September 2011

Opening IPtables for VSFTPD

While working with vsftpd configuring iptables is essential. It can be done as follows:



Here's the document I refer people to so that they can following the FTP protocol:http://slacksite.com/other/ftp.html
  • To do active-mode FTP, you need to allow incoming connections to TCP port 21 and outgoing connections from port 20.
  • To do passive-mode FTP, you need to allow incoming connections to TCP port 21 and incoming connections to a randomly-generated port on the server computer (necessitating using a conntrack module in netfilter)
You don't have anything re: your OUTPUT chain in your post, so I'll include that here, too. If your OUTPUT chain is default-drop then this matters.
Add these rules to your iptables configuration:
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 20 -j ACCEPT
To support passive mode FTP, then, you need to load the ip_conntrack_ftp module on boot. Uncomment and modify the IPTABLES_MODULES line in the /etc/sysconfig/iptables-config file to read:
IPTABLES_MODULES="ip_conntrack_ftp"
Save the iptables config and restart iptables.
service iptables save
service iptables restart
To completely rule out VSFTPD as being a problem, stop VSFTPD, verify that it's not listening on port 21 with a "netstat -a" and then run a :
nc -l 21
This will start netcat listening on port 21 and will echo input to your shell. From another host, TELNET to port 21 of your server and verify that you get a TCP connection and that you see output in the shell when you type in the TELNET connection.
Finally, bring VSFTPD back up, verify that it is listening on port 21, and try to connect again. If the connection to netcat worked then your iptables rules are fine. If the connection to VSFTPD doesn't work after netcat does then something is wrong w/ your VSFTPD configuration

References:

Thursday 22 September 2011

Error while loading shared libraries: libmysqlclient.so.16

While migrating custom mysql installation, I got this error. To resolve I followed the following procedure:


bin/postconf: error while loading shared 
libraries: libmysqlclient.so.16: cannot open 
shared object file: No such file or directory

This is because mysql library path is not in system library locations.
To fix the error edit /etc/ld.so.conf
vi /etc/ld.so.conf
Add following line to end of the file
/usr/lib/mysql

Now run ldconfig
ldconfig




Wednesday 21 September 2011

Removing old log files from backup scripts

#!/bin/bash
# script to remove confluence backups by modification time

find /opt/ -mtime +1 -type f -exec rm -rf {} \;




### This is quite simple one

VNC server on Centos 6.0

Was trying to configure vnc on centos 6. Following are the steps which I used.

#yum install vncserver


useraccount 'tom' was already created

therefore just logged on as the user and ran the following command to set the vnc password

#vncpasswd

which creates a .vnc directory under the home directory of the user

Edit the server configuration {/etc/sysconfig/vncservers } as follows

VNCSERVERS="1:tom"
VNCSERVERARGS[1]="-geometry 640x480"

Then restart the services:

#service vncserver start

Change the firewall settings by editing /etc/sysconfig/iptables and I had to allow the following as I had other users configured as well

-A INPUT -m state --state NEW -m tcp -p tcp --dport 5900 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 5901 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6001 -j ACCEPT


Now I can connect from ubuntu or realvnc clents from other workstations.

But I encountered the following error when restarting the system and service

A VNC server is already running as :10





When I checked the logs, what I saw was:

Starting up the machine number 10
Cannot bind the socket to the display. Error:1 at /usr/bin/vncserver line 275.
A VNC server is already running as :10


but checking for processes running on 5910 and 5810 showed that none were listening:

[root@myserver]$ netstat -an | grep 5910
[root@myserver]$ netstat -an | grep 5810
[root@myserver]$


after some searching, I finally found this link that lead me to the answer.
There was another stray process that was listening at tcp port 6010 as shown below

[root@myserver]$ /usr/sbin/lsof -i tcp:6010
COMMAND   PID USER   FD   TYPE    DEVICE SIZE NODE NAME
sshd    19464 root    8u  IPv4 143749109       TCP localhost.localdomain:x11-ssh-offset (LISTEN)


All I had to do was kill that process 19464 and then the vncserver was able to start up correctly.
ADDENDUM I finally found out what was causing it. It was my own ssh sessions to the server with X11Forwarding enabled that were causing the conflicts. So the ultimate resolution to the problem was to add the following into the "/etc/ssh/sshd_config" file.
X11DisplayOffset 50
and restart the sshd.


References:


1) http://monsterjam.org/blog/20071228103211
2)  http://wiki.centos.org/HowTos/VNC-Server

Thursday 15 September 2011

Resolving No hypervisor options were found for this connection error in kvm gui virt-manager


When trying to run the GUI “virt-manager,” I ran into this problem on a Dell server:
When I invoke virt-manager from the command line as root, then click new to create a guest OS, I get a warning/error message that reads:
Error: No hypervisor options were found for this connection.
This usually means qemu or kvm is not installed on your machine.  Please insure they are installed as intended.
When I go on to enter a name for the guest in the box, the forward button is grayed out.  However, clicking enter takes me to step 2.
Errors you’d see in /var/log/messages:
 Mar 11 06:18:27 myserver kernel: kvm: disabled by bios
Mar 11 07:11:31 myserver kernel: kvm: disabled by bios
Mar 11 08:39:09 myserver kernel: kvm: disabled by bios
 As it turns out, this quite annoying problem wasted a lot of time.  The solution was actually on the BIOS of the server, where there’s a switch to enable Virtualization.  After doing this and rebooting, KVM was able to load properly and allow for new VMs to be installed.

References:

http://willsnotes.wordpress.com/2011/04/30/rhel6-virtualization-issues-with-error-no-hypervisor-options-were-found-for-this-connection/

Friday 2 September 2011

Using mail command to send emails from script

I had to create a script which sends the output log file through e-mail but the mail's were not working as the main smtp server rejects emails from unknown domains such as "root@local.net" or "root@foo.bar.net" so I searched google and found some different way to send mails with the mail command in this situation.

Following are the tips which can help:

1) editing the sendmail.cf file to change the domain name while sending emails:



edit your sendmail.cf file (should be in /etc)
Scroll down to the

##################
#   local info   #
##################

section and look for these lines:

# my official domain name
# ... define this only if sendmail cannot automatically determine your domain
#Dj$w.Foo.COM
^^^^^^^^^^^^^ copy/paste this line

uncomment the copy and change this line so that it looks like this:

Djitercom.org

the Dj are important - dont edit them out.  Save your changes and send yourself a test email.

The email you recieve should now have the user it was sent from followed by your preferred domain name - instead of the node and complete domain name



I had to put a space between DJ and itercom.org (e.g. Dj itercom.org) to make it work.

ps - if you want to see what your version is and some other info, type this:

/usr/lib/sendmail -d0 -bt < /dev/null

the character after -d in the above is a zero.

You should get output similar to this:

Version AIX5.3/8.11.6p2
 Compiled with: _FFR_MILTER LDAPMAP MAP_REGEX LOG MATCHGECOS MIME7TO8
                MIME8TO7 NAMED_BIND NDBM NETINET NETINET6 NETUNIX NEWDB NIS
                NISPLUS QUEUE SCANF SMTP USERDB XDEBUG

============ SYSTEM IDENTITY (after readcf) ============
      (short domain name) $w = somenode
  (canonical domain name) $j = somenode.somedomain.com
         (subdomain name) $m = somedomain.com
              (node name) $k = somenode
========================================================

ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter



Note: you will see  your host name and domain in place of somenode and somedomain. 

 
 2) changing the from address on the command line as a option to mail command


On Centos I'm able to do:
mail -s "Subject" user@address.com -- -f from@address.com < body
The double dash stops mail from parsing the -f argument and passes it along to sendmail itself.

References: