Linux - Looking under the hood

How to build a statically linked binary for a 32bit environment on a 64bit platform ?

  • I am far from being a specialist, so consider the information below cautiously : there may be missing / wrong / context-specific information. Use at your own risks.
  • sshpass may not be the best software in town as it leads to unsafe workflows (details) but in the context of this article (learning to build a custom binary), it does the job. Use the generated binary at you own risks (or —myadvice— just delete it once you've learnt everything you needed ).

Get the source code of the software you'd like to compile :

The fastest + easiest solution :
apt-get source sshpass
This requires :
  • the software to be available in your distro's list of packages
  • and your workstation to have a deb-src ... entry in /etc/apt/sources.list
This Debian wiki page gives a good description of what you'll get and alternate means.

Now, make it happen (inspired by) :

apt-get source sshpass
cd sshpass-1.06/
./configure
make
ldd sshpass
linux-vdso.so.1 (0x00007ffe45de8000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3830e37000)
/lib64/ld-linux-x86-64.so.2 (0x00007f38313da000)
make clean
make SHARED=0 CC='gcc -static'		not sure about the SHARED=0 part 
ldd sshpass
not a dynamic executable		what we were trying to do 
What happens after moving our new binary to 32bitMachine ?
kevin@32bitMachine ~$ ./sshpass
bash: ./sshpass: cannot execute binary file
kevin@32bitMachine ~$ file sshpass
sshpass: ELF 64-bit LSB executable, AMD x86-64, version 1 (GNU/Linux), for GNU/Linux 2.6.32, statically linked, not stripped
kevin@32bitMachine ~$ uname -a
Linux 32bitMachine 2.6.9-89.0.3.ELsmp #1 SMP Sat Jun 13 07:05:54 EDT 2009 i686 i686 i386 GNU/Linux

At that time, I didn't notice it, but I was also not building for the right kernel version : 2.6.32 vs 2.6.9 .

After that, I read + tried various methods that FAILED until... :

I note them here because knowing what doesn't work, albeit not the solution, is part of the solution (and possibly —later— I'll understand why they failed ).
  1. (source)
    ./configure --host=i686-linux-gnu --build=i686-linux-gnu CC="gcc -m32" CXX="g++ -m32" CFLAGS="-O2 -march=i686" CXXFLAGS="-O2 -march=i686"
    checking for a BSD-compatible install... /usr/bin/install -c
    checking whether build environment is sane... yes
    checking for a thread-safe mkdir -p... /bin/mkdir -p
    checking for gawk... gawk
    checking whether make sets $(MAKE)... yes
    checking whether make supports nested variables... yes
    checking for style of include used by make... GNU
    checking for i686-linux-gnu-gcc... gcc -m32
    checking whether the C compiler works... no
    configure: error: in `.../path/to/sshpass-1.06':
    configure: error: C compiler cannot create executables
    See `config.log' for more details
  2. (source)
    make clean && ./configure && make CC='gcc -static -m32'
    make  all-am
    make[1]: Entering directory '.../path/to/sshpass-1.06'
    gcc -static -m32 -DHAVE_CONFIG_H -I.     -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
    main.c:25:23: fatal error: sys/types.h: No such file or directory
     #include <sys/types.h>
                           ^
    compilation terminated.
    Makefile:415: recipe for target 'main.o' failed
    make[1]: *** [main.o] Error 1
    make[1]: Leaving directory '.../path/to/sshpass-1.06'
    Makefile:307: recipe for target 'all' failed
    make: *** [all] Error 2
  3. (source)
    apt-cache search libc | grep -E 'dev.*86'
    libc6-dev-i386 - GNU C Library: 32-bit development libraries for AMD64
    apt install libc6-dev-i386
    make clean && ./configure && make CC='gcc -static -m32'
    make  all-am
    make[1]: Entering directory '.../path/to/sshpass-1.06'
    gcc -static -m32 -DHAVE_CONFIG_H -I.     -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
    In file included from /usr/include/sys/ioctl.h:26:0,
                     from main.c:28:
    /usr/include/bits/ioctls.h:23:24: fatal error: asm/ioctls.h: No such file or directory
     #include <asm/ioctls.h>
                            ^
    compilation terminated.
    Makefile:415: recipe for target 'main.o' failed
    make[1]: *** [main.o] Error 1
    make[1]: Leaving directory '.../path/to/sshpass-1.06'
    Makefile:307: recipe for target 'all' failed
    make: *** [all] Error 2
  4. (source)
    apt install gcc-multilib
    make clean && ./configure && make CC='gcc -static -m32'
    no error
    file sshpass
    sshpass: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=886a41e4c4e7631776b20a44f2262b85ad3fa240, not stripped

Let's move again our new binary to 32bitMachine :

kevin@32bitMachine ~$ file sshpass
sshpass: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), for GNU/Linux 2.6.32, statically linked, not stripped
kevin@32bitMachine ~$ (a command including sshpass)
FATAL: kernel too old
Segmentation fault
Indeed :
kevin@32bitMachine ~$ uname -a
Linux 32bitMachine 2.6.9-89.0.3.ELsmp #1 SMP Sat Jun 13 07:05:54 EDT 2009 i686 i686 i386 GNU/Linux
I compiled for a 2.6.32 kernel, while I have a 2.6.9.
Back to my 64bit workstation, I tried :
make clean && ./configure --enable-kernel=2.6.9 && make CC='gcc -static -m32'
... but it's not that simple

Conclusion :

I've not been able to build a binary as I wanted to. However, I've learnt some extra things in the process, which is GOOD .

Let me conclude with an inspiring quote by Bruce Lee :

Don't fear failure. Not failure, but low aim, is the crime. In great attempts it is glorious even to fail.

Process priority (PR) vs niceness (NI)

Why can't I delete or rename a file I own with 700 rights ?

  1. tempDir=$(mktemp -d tempDir.XXXXXXXX); touch "$tempDir/file1" "$tempDir/file2"
  2. chmod 000 "$tempDir/file1"; chmod 700 "$tempDir"; rm "$tempDir/file1"
    rm: remove write-protected regular empty file 'tempDir.AVVTQONL/file1'? y			Not completely happy but does it though
  3. chmod 700 "$tempDir/file2"; chmod 000 "$tempDir"; rm "$tempDir/file2"
    rm: cannot remove 'tempDir.AVVTQONL/file2': Permission denied					Total disagreement. Why ?
  4. mv "$tempDir/file2" "$tempDir/file3"
    mv: failed to access 'tempDir.AVVTQONL/file3': Permission denied				"Why ?" again 
  5. chmod 700 "$tempDir"; rm "$tempDir/file2"; rmdir "$tempDir"
This is because deleting or renaming a file actually alters its parent directory, not the file itself. In Unix, a directory is just a file containing a list of files.

How to install new fonts ?

  1. make a new directory for fonts :
    mkdir -p ~/.local/share/fonts
  2. copy font files there
  3. rebuild the font cache :
    fc-cache -f -v

To make a font available to all users, copy it into /usr/share/fonts instead.

On the Internets, some answers / comments specify ~/.fonts as the personal fonts dir, while others prefer ~/.local/share/fonts. Some even state one or the other should be preferred or is obsolete...

What if I accidentally moved /* to a different location ?

Situation :

Don't type the commands below since I'm basically explaining here how I shot my own leg

What I meant is :
mv $D/* .
$D being an existing directory, and . the location I wanted files to land into.
But I actually typed :
mv $d/* .
... and did this as root.

Details :

When receiving the command :
mv $d/* .
Bash will expand variables. Here, since $d is undefined, it is considered as an empty string, and my command becomes :
mv /* .
I stopped it as quick as I could with CTRL-c, but /bin and /lib (and many others) were already gone . What's "fun" then is that the shell commands ls, cp or mv don't work anymore since there is no /bin/ls, /bin/cp or /bin/mv. Even invoking binaries as ./bin/ls, ./bin/cp or ./bin/mv fails : /lib64/ld-linux-x86-64.so.2: bad ELF interpreter, they say (but no big surprise either since /lib and /lib64 have been moved to...). And I can't even create symlinks because I have no /bin/ln anymore .

Solution :

In such situation, there are not many solutions. The obvious one is to boot the computer on a rescue media, mount the partition and restore files manually to their normal location.

But another solution may save your life : BusyBox. This is a binary with lots of standard utilities (like mv, sh, ls, ...) built into it. To restore the system, you just have to :

busybox mv {bin,boot,dev,etc,lib,lib64} /

To prevent this from happening again, I considered adding set -u to ~/.bashrc, but this breaks the TAB completion. (investigate this !!!)

I'm having DNS resolution issues and /etc/resolv.conf is continuously overwritten

Situation :

Well, it's all in the title.

Details :

The DNS servers configured in /etc/resolv.conf don't provide any useful service anymore (problem on ISP side ?)

Solution :

systemctl -a | grep resolv
	pppd-dns.service			loaded	inactive dead	Restore /etc/resolv.conf if the system crashed before the ppp link was shut down.

systemctl status pppd-dns.service

 pppd-dns.service - Restore /etc/resolv.conf if the system crashed before the ppp link was shut down.
	Loaded: loaded (/lib/systemd/system/pppd-dns.service; enabled)
	Active: inactive (dead) since Sat 2016-02-27 14:36:27 CET; 3 weeks 1 days ago
 Main PID: 619 (code=exited, status=0/SUCCESS)

Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.


nameserver 2001:41d0:3:163::1
nameserver 2001:41d0:1:e2b8::1


systemctl disable pppd-dns.service
	Synchronizing state for pppd-dns.service with sysvinit using update-rc.d...
	Executing /usr/sbin/update-rc.d pppd-dns defaults
	Executing /usr/sbin/update-rc.d pppd-dns disable
	insserv: warning: current start runlevel(s) (empty) of script `pppd-dns' overrides LSB defaults (S).
	insserv: warning: current stop runlevel(s) (S) of script `pppd-dns' overrides LSB defaults (empty).

/etc/init.d/pppd-dns stop
update-rc.d pppd-dns remove

==> Still not working :-(
This is quick and dirty, but works until I find WTF is going on :
echo -e 'nameserver 208.67.222.222\nnameserver 208.67.220.220' > /etc/resolv.conf && chattr +i /etc/resolv.conf

How to change the default text editor ?

Even though I'm rather an Emacs guy (especially when it comes to development), I've learnt the basics of Vi and I admit it's more than enough for quick edits like configuration files, crontabs, Git commit messages, ... On top of that, I don't particularly appreciate Nano and I just can't get used to its keyboard shortcuts (yeah : kinda weird in an Emacs/Vi talk, I know ), and I _always_ have to look at the bottom line reminding me of them.
Enough is enough : how can I just change that to a decent text editor ?

Temporary solution :

  1. Run : export EDITOR=vi|emacs|nano
  2. Check it with : crontab -e

Permanent solution :

  1. Append to ~/.profile :
    export EDITOR=vi|emacs|nano
  2. Reload changes : source ~/.profile
  3. Check it with : crontab -e

Permanent Debian-specific solution :

  1. As root, run : update-alternatives --config editor
  2. Follow the on-screen instructions
  3. Check it with : crontab -e
Tested but doesn't seem to work on Debian Jessie Try : select-editor.

How to stop the X Server ?

Situation :

For any reason, I need to turn off the X Server. How to proceed ?

Details :

This can be done easily by switching to a lower runlevel with init newRunlevel
However, this doesn't work on Debianoids if network or multiuser are required since the default runlevel is 2.

Solution :

Stop the display manager, which can be : If necessary, it's possible to explicitly stop (kill) the X Server with : Ctrl-Alt-[backspace]

Linux performance tools

Observability :

  • /proc
  • blktrace
  • dstat
  • dtrace
  • ebpf
  • ethtool
  • free
  • ftrace
  • iostat
  • iotop
  • ip
  • iptraf
  • ktap
  • lldptool
  • ltrace
  • lttng
  • mpstat

Tuning :

How to stop the /usr/sbin/ModemManager process and prevent it from restarting ?

Situation :

  • This article has little to nothing practical use except for some future reference or further investigations on the D-Bus service
  • In previous software versions, we had :
    • process name : modem-manager
    • binary : /usr/sbin/modem-manager
    • service name : ModemManager1.service
    • D-BUS file : /usr/share/dbus-1/system-services/org.freedesktop.ModemManager.service

top -p $(pidof ModemManager)

PID	USER	PR	NI	VIRT	RES	SHR	S	%CPU	%MEM	TIME+	COMMAND
553	root	20	0	422444	8724	7244	S	0.0	0.2	0:00.04	ModemManager
which looks BAD to me as I don't use a modem anymore.

Details :

ModemManager is a child process of Network Manager : if you try to kill ModemManager, NetworkManager will try to start it again.
ModemManager is implemented as a D-Bus service and it's autostarted by D-Bus when a call is made on it. NetworkManager pokes it every 2 minutes and thus restarts it.

Solution :

To disable it :
  1. Make sure it's alive : top -p $(pidof ModemManager)
  2. mv /usr/share/dbus-1/system-services/org.freedesktop.ModemManager1.service{,_DISABLED}
  3. kill -1 $(pidof ModemManager)
  4. make sure it's dead : ps aux | grep [M]odemManager
  5. Congratulations : you've just saved about 8MB of memory (the RES part)

Alternate solution :

systemctl stop ModemManager.service; systemctl disable ModemManager.service

/var/log/auth.log is missing

Situation :

  1. The file /var/log/auth.log is missing. No process has even tried to create it, nor complained about it not found.
  2. If I create it manually with 640 permissions and owning it by root:adm, no process even tries to write into it.

Details :

Creating log files manually is useless : should any process require a log file, it will create it if missing.
/var/log/auth.log is declared in /etc/rsyslog.conf.

Solution :

In my situation, restarting rsyslogd made it back to normal : /etc/init.d/rsyslog restart

How to recover deleted / lost / corrupted files ?

It is possible to recover a deleted file with lsof provided there is still a process holding it. Otherwise, keep reading below.

Using Scalpel :

  1. install : apt install scalpel
  2. edit /etc/scalpel/scalpel.conf (append rules such as these for OpenOffice files)
  3. edit the recovered file size (10MB on this example) : upon finding the start tag, Scalpel will recover 10MB as if they were part of the recovered file.
  4. umount the volume to analyze
  5. mkdir -p /directory/for/recovered/files
  6. scalpel /dev/sdXY -b -o /directory/for/recovered/files
  7. wait...
  8. once done, hope you'll find anything valuable in /directory/for/recovered/files
Flags (need more details):
-b : recover a file even if it's missing a footer
-o : output directory (?)

How to limit users' resource usage ?

With /etc/security/limits.conf and PAM (details) :

  1. Make sure PAM limits are enabled (source) : in /etc/pam.d/login, you should have
    session	required	pam_limits.so
  2. To limit the maximum number of processes for a given user, add into /etc/security/limits.conf a line such as (source, configuration details) :
    stuart hard nproc maximumNumberOfProcesses
  3. At this step, settings will be applied after stuart's next login. To reload settings now : sudo -i -u stuart (source)
  4. Then, as stuart, check that limits settings have been reloaded : ulimit -a
  5. A potentially unsafe QnD solution would be to restart the init process : kill -HUP 1 (source)

With /etc/limits and shadow :

(old-style method, deprecated by PAM)

... or with ulimit.

How to handle text file encoding and transcode between us-ascii, iso-8859-15, utf-8, ..., charsets ?

Detect file encoding

You can detect file encoding with : file -i fileName.

  • If this returns the file MIME type instead of its encoding, you may try creating a new file next to fileName : it's very likely to have the same encoding.
  • If fileName contains no special character (i.e. ASCII characters only), its charset will be a basic *-ascii. To have it use an "advanced" charset, it must contain some non-ASCII characters : éêèàâî....

Transcode

From the shell :
  • iconv --from-code=ISO-8859-1 --to-code=UTF-8 iso_file.txt > utf8_file.txt

    The source and destination must be distinct files.

    fileToTranscode='itr_install_db_050000.ksh'; cp "$fileToTranscode"{,_BITI}; iconv --from-code=ISO-8859-1 --to-code=UTF-8 "${fileToTranscode}_BITI" > "$fileToTranscode"

  • recode Latin1..UTF8 file.txt (recode -l to list available encodings)
With Emacs (source : 1, 2) :
  1. Open the file to transcode
  2. Notice some letters in the lower left corner identifying the charset :
    Letters charset Comment
    UU- us-ascii
    UU0 iso-8859-15 file -i reports iso-8859-15 as iso-8859-1
    UU1 iso-8859-1
    UUU utf-8
    • CTRL-x f
    • OR : CTRL-x CTRL-m f
  3. At the prompt, type the new coding system : iso-8859-1 / utf-8 / ...
  4. Save the transcoded file
With Vim (source) :
  1. Open the file to transcode
  2. :write ++enc=utf-8
With Notepad++ :
There is a built-in transcoding function : Encoding | Convert to ....

How to alter environment variables of a running process ?

Method 1 (source) :

  1. gdb -p PID (consider $(pidof command))
  2. (gdb) p setenv("variableName", "variableValue")
  3. (gdb) q
  4. (gdb) Really detach? y

Method 2 (source) :

  1. gdb
  2. (gdb) attach PID
  3. (gdb) call putenv ("variableName"="variableValue")
  4. (gdb) detach
  5. (gdb) y

File permissions and setuid / setgid / sticky bits

Basic file permissions

Example File type All
User Group Others
-rw-r--r-- regular file
  • r : read permission
  • w : write permission
  • x : execute permission
drwxr-xr-x directory
  • r : the contents of the directory can be shown
  • w : new files can be created
  • x : a user can cd into this directory

Special Permissions (source : RedHat, Wikipedia)

the Setuid bit
used only for binaries or scripts, this permission indicates that the file is to be executed with the permissions of the owner of the file, and not with the permissions of the user executing the file (which is the case without setuid). This is indicated by the character s in the place of the x in the owner category. If the owner of the file does not have execute permissions, a capital S reflects this fact.
the Setgid bit
used primarily for binaries, this permission indicates that the file is executed with the permissions of the group owning the file and not with the permissions of the group of the user executing the file (which is the case without setgid).
If applied to a directory, all files created within the directory are owned by the group owning the directory, and not by the group of the user creating the file. The setgid permission is indicated by the character s in place of the x in the group category. If the group owning the file or directory does not have execute permissions, a capital S reflects this fact.
the Sticky bit
used primarily on directories, this bit dictates that a file created in the directory can be removed only by the user who created the file. It is indicated by the character t in place of the x in the everyone category. If the everyone category does not have execute permissions, the T is capitalized to reflect this fact.
Under Red Hat Enterprise Linux, the sticky bit is set by default on the /tmp/ directory for exactly this reason.

Octal Permissions

Bit Symbol Number
setuid s 4000
setgid s 2000
sticky t 1000 If this attribute is assigned to a directory, it will prevent users from deleting each other's files.
r 400 for user, 40 for group, 4 for other
w 200 for user, 20 for group, 2 for other
x 100 for user, 10 for group, 1 for other

Environment Variables

Definition (source 1, 2) :

An environment variable is basically just a shell variable that is available system-wide (i.e.: to sub-shells). A shell variable can be changed into an environment variable with export.

List all environment variables :

  • $ + TAB : names only. By convention, environment variables names are all UPPERCASE.
  • export -p
  • printenv
  • env or set : names and values (need details of the difference, if any)

Display the value of an environment variable :

  • env | grep VARNAME
  • printenv VARNAME
echo $VARNAME
doesn't discriminate environment from shell variables and will always display the corresponding value (or nothing if unset).

Alter temporarily (source) :

  1. VARNAME=value
  2. This value will last as long as the current Bash is running (=until logout or exit). To spread the new value to the child processes of the current Bash, you must export it : export VARNAME

An alternate solution (in bash/ksh/zsh) may be to ignore the whole environment to run a single command : env -i anyCommand (source)

You can also set a shell variable so that its scope is limited to a single command by placing it just before this command (source) :
foo=bar bash -c 'echo "$foo"'; echo "$foo"
bar
(empty line)
foo=bar bash -c echo\ $foo; echo "$foo"
(empty line)
(empty line)

Alter permanently (sources : 1, 2) :

Keep in mind that
  • changes made in ~/whatever will only exist in the current user scope
  • changes made in /etc/whatever will exist system-wide
Depending on the shell type, i.e. (non-)?(login|interactive) :
  1. edit one of :
    • ~/.bashrc
    • ~/.bash_profile
    • ~/.profile
    • /etc/profile
  2. add export VARNAME=value
  3. reload changes : source theFileYouJustEdited
Example :
export http_proxy=http://bob:password@host:port/
export https_proxy=$http_proxy
in /etc/environment (source) :
http_proxy=http://bob:password@host:port/
https_proxy=https://bob:password@host:port/
when it comes to the http_proxy configuration, things may get shitty when using wget, because of its configuration files that may also have some additional / conflicting settings :
  • /etc/wgetrc
  • ~/.wgetrc
Consider giving a try with curl to have a clear picture of what's going on

Set with :

  • Bash : export VARNAME=value This is NOT permanent !
  • C-Shell : setenv VARNAME value

Unset with :

unset VARNAME

How to manage users and groups

On a Linux system, users belong to 2 group types :

Action Linux FreeBSD
add a user account adduser + follow on-screen instructions
delete a user account userdel -r kevin
-r : delete the user's home directory too.
rmuser kevin
lock a user account usermod -L kevin Details about LOCKED accounts
unlock a user account
usermod -U kevin
This removes the ! in front of the encrypted password in /etc/shadow
get date of latest user login lastlog | grep kevin
create a new group groupadd newGroupName pw group add groupName
delete a group pw group del groupName
list all groups less /etc/group (also shows group members) pw group show -a
add a user into an existing group
  • Primary group : pw usermod kevin -g groupName
  • Group list : pw usermod kevin -G current,groups,groupName
remove a user from a group
  • gpasswd -d kevin groupName
  • deluser kevin groupName
  • edit /etc/group
list the members of a group grep 'groupName' /etc/group
  • grep 'groupName' /etc/group
  • pw group show groupName
list the last n logins of a user last -n stuart | less
List the groups a user belongs to
to know which unix users are currently connected who
to read details about a user account on a local/distant host
  • finger
  • finger kevin@host
  • finger @host

About the FreeBSD LOCKED accounts (source) :

  • Check whether an account is LOCKED :
    • vipw (to edit the password file with vi)
    • or : less /etc/master.password

    This will display the users list, the encrypted passwords and *LOCKED* before it when applicable.

  • How to lock a user account :

    pw lock kevin

  • Now, this user can not log in anymore into telnet, ftp, ssh and rlogin. But he still has access to Samba.

How to create a loop filesystem ?

The loop devices are a possibility under GNU/Linux to mount regular files. It is often used to mount an iso image, but it can also be used to play with RAID, LVM, or a file system.
Loading the loop module is required before using loop devices : modprobe loop. This will create the loop devices /dev/loop0, /dev/loop1, etc.
Consider working inside a tmpfs like /dev/shm to gain speed when running tests.

Create a filesystem out of a file, then mount it :

  1. Create a file having the size of your future filesystem : dd bs=1M count=100 if=/dev/zero of=fsInAFile
  2. Format the file (using any filesystem you like) : mkfs.ext4 fsInAFile
    mkfs will ask : fsInAFile is not a block special device. Proceed anyway? (y,n). Answer y.
  3. Mount the file with a loop device : mount -o loop fsInAFile /path/to/mount/point
    When using the option -o loop the first available loop device is taken. It is possible to select the loop device to use by giving the option -o loop=/dev/loop0.
  4. You can check that the device is perfectly mounted with mount. It should display a line such as :
    fsInAFile on /mount/point type ext4 (rw,loop=/dev/loop0)
  5. It is now possible to create files and directories within /mount/point, then unmount the device and remount it back as any removable device.

Convert files between DOS and Unix formats

Operating systems differ on the way they handle the newline character :
OS family newline character displayed character Character code
Unix (Linux, *BSD, Mac OS X) LF \n 0x0a
Apple (before Mac OS X) CR \r 0x0d
MS-DOS, Windows CR+LF \r\n 0x0d0a

Files can be converted with utilities :

Convert files from DOS to Unix :

  • convert and replace file :
    • dos2unix file
    • fromdos file
  • convert and create new file :
    • dos2unix -o originalFile newFile
    • fromdos -b file (file will be renamed as file.bak)

Runlevels

With systemd coming, this is becoming obsolete.

Runlevels are defined in /etc/inittab :

Runlevel on Debianoids
(source 1, 2)
on Red Hatoids
0 system halt
1 single user mode
2 full multi-user mode (default) local multi-user mode without remote network (i.e. NFS)
3 full multi-user mode with network
4 (not used)
5 full multi-user mode with network and XDM (default)
6 system reboot

To detect the current runlevel : /sbin/runlevel.

How to install software from sources with .tar.gz, .tgz, .tar.bz2, .tbz packages ?

On Linux (and other Unices), file extensions have no special meaning for the system. They're just a hint for users to "guess" what's inside any given file. Linux would perfectly work without these, as it determines a file type (and what it can do with it) from file headers. See file for details.

To install such a package :

  1. uncompress it:
    • for gzip'ed archives : gunzip archiveName.tar.gz
    • for bzip2'ed archives : bunzip2 archiveName.tar.bz2
    This will result in a archiveName.tar file.
  2. unpack it: tar -xf archiveName.tar
    It _may_ create a directory called archiveName depending on how the archive was created.
  3. you can also uncompress + unpack in a single operation : tar -zxf archiveName.tar.gz or tar -xjf archiveName.tar.bz2
  4. inside the corresponding directory, have a look at the README file.
  5. ./configure
  6. make
  7. as root : make install

Generate a custom and optimized /etc/apt/sources.list

  1. append deb http://ftp.fr.debian.org/debian/ lenny stable main to /etc/apt/sources.list to be able to install netselect-apt
  2. apt-get install netselect-apt
  3. configure it to your Debian version : netselect-apt -n lenny stable (-n is to include non-free packages)
  4. netselect-apt will run some tests and generate a custom sources.list in the current directory. Edit it and uncomment the lines matching your needs.
  5. copy the new sources.list as /etc/apt/sources.list (should be smart to backup the previous one, or copy-paste lines from the new to the previous)
  6. then : apt-get update

LILO details

The first 512 bytes of the HDD are called the MBR. At boot time, the BIOS :
  1. reads the MBR
  2. loads the MBR into memory
  3. executes the MBR

The MBR can not actually store the Linux kernel itself since the kernel is about 500Kb. This is why the MBR only holds a loader that locates the kernel on the HDD then loads it into memory.

LILO itself is about 5Kb, which means still too big to fit the MBR ! Hence, LILO is split in 2 parts:
  1. one 512 bytes section that is designed to fit the MBR. Its role is to load the 2nd part of LILO.
  2. another one that contains the remaining, stored in /boot/boot.b

At boot time, the word LILO is displayed, printing letters one by one to show the booting steps:

  1. LILO then expects a parameter indicating which kernel (Linux or other system) is to be loaded.
  2. Once this parameter has been received (from user input or default choice (1st /etc/lilo.conf entry) after timeout), LILO reads /boot/map to find out which HDD blocks contain the required kernel.
  3. LILO loads those blocks into memory. Loading Linux .... is displayed.
  4. The kernel is uncompressed. Uncompressing Linux .... is displayed.
  5. Once uncompression is done, OK, booting the kernel. is displayed: the kernel starts.

Related files :

How to handle RPM packages ?

Command line Function Details
rpm -i packageName installs the RPM called packageName rpm -ivh packageName shows installation progress
rpm -i packageName --nodeps installs the RPM called packageName without checking dependencies
rpm -U packageName updates the RPM called packageName : install the new version and remove the old one.
rpm -e packageName uninstalls the RPM called packageName
rpm -q pattern queries the installed RPM's database for a RPM which name begins with pattern ex: rpm -q kernel-source
rpm options:
  • q : query
  • a : all
rpm -qa | grep -i pattern queries the installed RPM's database for a RPM which name contains pattern
rpm -qa pattern does nothing, displays nothing but returns a Unix success (0) return code.
rpm -qpl packageName displays the content of packageName, which is a non-installed RPM.
rpm -ql packageName displays the content of packageName, which is an installed RPM. Also try : rpm -qi --filesbypkg packageName (source)
rpm -qf fileName shows which RPM the file fileName comes from.
rpm -rebuilddb rebuilds the RPM database