Tag Archives: gnu/linux

Debian squeeze en Samsung N210

La semana pasada me compré una netbook Samsung N210 con la cual estoy muy contento. Le instalé Debian squeeze (testing) y logré configurarle todas las teclas especiales, incluyendo las usadas para regular el brillo de la pantalla. Me basé en varias guías como esta y esta otra, aunque no las seguí exactamente y es por eso el motivo del post.

Antes de comenzar la guía (y suponiendo que como yo, estás leyendo esto antes de comprar la máquina) te cuento mi experiencia con este aparatito. Algo que me hacía dudar en comprarme o no una netbook era el teclado que traían: demasiado chicos o sin espacio entre teclas. La N210 tiene casi la misma distancia entre la A y la Ñ que los teclados de escritorio y además tiene las teclas separadas como para que los dedos reconozcan mejor dónde están ubicados. Lo encuentro bastante cómodo y agradable de usar y salvo por un par de teclas que complican un poco (la < se encuentra sobre la derecha y el shift derecho es chico) me siento a gusto con él. Por otro lado la batería dura aprox. 7 hs (con el brillo casi a tope) contra las 11 que declara Samsung. Dudo que llegue a eso incluso desconectando la wifi, bluetooth y poniendo el brillo al mínimo, pero aun así destaca su autonomía. Otra característica que me gusta es que es silenciosa y calienta muy poco.

Una última cosa antes de comenzar: El microprocesador Atom N450 tiene tecnología Hyperthreading que paraleliza el procesador físico en dos procesadores virtuales. Es por eso que la salida de/proc/cpuinfomuestra dos cpus.

Ahora sí, vamos a la guía.


Read more »

Tags: , ,

Reemplazo de discos en RAID con mdadm

Hace unos días hice mi segundo reemplazo completo de discos de un array MD y quería compartir aquí los pasos que he utilizado (con éxito :D) en ambos casos.

Los dos escenarios fueron similares: dos discos iguales, con iguales particiones y RAID-1 que deben ser reemplazados por otros dos discos iguales pero de mayor tamaño, por lo que el procedimiento fue el mismo en ambos casos.

Para simplificar la guía decidí usar discos con sólo tres particiones: una para/, una para/vary otra paraswap(que no está en RAID). El esquema entonces queda definido de la siguiente manera:

sda (grub)               RAID's 1                sdb (grub)
+------------------+     +-----------------+     +------------------+
| /dev/sda1        |-----| /dev/md0 (/)    |-----| /dev/sdb1        |
+------------------+     +-----------------+     +------------------+
| /dev/sda2        |-----| /dev/md1 (/var) |-----| /dev/sdb2        |
+------------------+     +-----------------+     +------------------+
| /dev/sda3 (swap) |                             | /dev/sdb3 (swap) |
+------------------+                             +------------------+

Los discos que se usarán para reemplazo sonsdcysdd.

NOTA: En la guía sólo se muestra el reemplazo completo de sda por sdc ya que el procedimiento para reemplazar sdb por sdd es el mismo.

1. Particionado de disco

La manera sencilla de copiar la tabla de particiones de una unidad a otra es:

papua:~# sfdisk -d /dev/sda | sfdisk /dev/sdc

Esto copia completamente el esquema del disco origen (sda) al disco destino (sdc). Si el destino es mayor simplemente quedará espacio libre (sin asignar) al final del disco.

2. Reemplazo de particiones en arrays

TIP: Es útil tener visible, en otra terminal y durante todo el proceso, la salida de/proc/mdstatpara visualizar en todo momento el estado del array y poder ver el sincronizado de los discos:

papua:~# watch -t cat /proc/mdstat


Read more »

Tags:

Sincronizar Motorola Q y Evolution con SynCE y MultiSync en Ubuntu Jaunty

Para sincronizar contactos, calendario y tareas entre un Motorola Q y Evolution se necesitan dos programas: SynCE y MultiSync.

Como dice el sitio web de SynCE, el objetivo del proyecto es proporcionar un medio de comunicación entre un dispositivo con Windows Mobile y un equipo con Linux, *BSD u otro UNIX, mediante una conexión USB o Bluetooth. Esto permite utilizar la PC para navegar el sistema de archivos del teléfono e instalar aplicaciones y proporciona el medio de comunicación para que mediante otro programa (MultiSync) sea posible sincronizar contactos, calendario y tareas entre el teléfono y una aplicación PIM de escritorio como Evolution.

MultiSync es una herramienta de software libre que sincroniza calendarios, libretas de direcciones y otra información PIM, entre programas de una PC o de otras PC, dispositivos móviles o teléfonos móviles. Depende del framework de desarrollo OpenSync.


Read more »

Tags: ,

umask

Umask (user mask) es un número octal que UNIX utiliza para determinar qué permisos NO asignar automáticamente a los nuevos archivos y directorios creados. Umask sólo restringe permisos; no concede permisos adicionales más allá de lo especificado por defecto.

La mayoría de los sistemas UNIX especifican el valor octal 666 (rw-rw-rw-) para la creación de archivos y el valor octal 777 (rwxrwxrwx) para la creación de directorios. Luego, el kernel utiliza el valor de umask asignado al usuario como máscara para quitar permisos a los definidos por defecto. Todo proceso tiene su umask, heredado del proceso padre del cual desciende.

Los valores más comunes para umask son 022, 027 y 077.
Normalmente el valor de umask se define en /etc/profile

# Set the user's umask
umask 022

aunque es posible setearlo en algún archivo de sesión como ~/.bash_profile, e incluso manualmente para la sessión actual. En todos los casos se utiliza el comando umask que es una función interna de Bash, y de otros shells como ksh y csh. (Si umask fuera un programa separado del shell no podríamos cambiar el valor de umask del proceso shell actual).

Cálculo de permisos

Los permisos de creación se obtienen realizando un AND binario entre el permiso por defecto y el complemento unario (NOT binario) de umask:

Suponiendo que quisiéramos averiguar los permisos de creación de archivos y directorios para umask 027:

permisos archivos:    666 & ~027
permisos directorios: 777 & ~027

Recordemos que el complemento unario puede obtenerse fácilmente reemplazando ceros por unos y unos por ceros:

Complemento unario:
 027 = 000 010 111
~027 = 111 101 000

Luego de obtener el complemento unario se procede a realizar el AND binario:

Archivos:
 666 = 110 110 110
~027 = 111 101 000
------------------
 640 = 110 100 000  <-- (rw-r-----)
Directorios:
 777 = 111 111 111
~027 = 111 101 000
------------------
 750 = 111 101 000  <-- (rwxr-x---)

En bash

$ umask 027
$ mkdir foo
$ touch bar
$ ls -l
drwxr-x---  2 xleo xleo    48 2009-08-19 01:09 foo
-rw-r-----  1 xleo xleo     0 2009-08-19 01:10 bar

Referencias

Tags: ,

Tiempos de ejecución de un proceso

Traducción de What do ‘real’, ‘user’ and ‘sys’ mean in the output of time?

$ time foo
real  0m13.520s
user  0m1.628s
sys   0m1.420s
Real
Tiempo real transcurrido desde que el proceso comienza hasta que finaliza. Esto implica el tiempo utilizado por otros procesos ejecutándose al mismo tiempo y el tiempo en que el proceso se encuentra bloquedo (por ejemplo, esperando que una llamada al sistema como I/O se complete).
User
Tiempo de CPU empleado por el proceso en modo usuario (fuera del núcleo). El tiempo de CPU de otros procesos y el tiempo de espera de una llamada al sistema no cuentan en este valor.
Sys
Tiempo empleado por el núcleo para atender peticiones del proceso. Esto significa tiempo de uso de CPU en llamadas al sistema dentro del núcleo, como por ejemplo I/O.

User+Sys equivale al total de tiempo de CPU usado por el proceso.


Read more »

Tags:

GNU gettext con php5

gnu-head-sm

GNU gettext es la biblioteca GNU de internacionalización (i18n) y es usada para escribir programas con interfaz en múltiples idiomas.

wikipedia

La internacionalización es el proceso de diseñar software de manera tal que pueda adaptarse a diferentes idiomas y regiones sin necesidad de cambios de ingeniería ni de código. La localización es el proceso de adaptar el software para una región específica mediante la adición de componentes específicos de un locale y la traducción de los textos, por lo que también se le puede denominar regionalización.

Es una práctica común en el idioma inglés (sobre todo en el ámbito de la computación), abreviar internationalization como “i18n”. Ello se debe a que entre la primera i y la última n de dicha palabra hay 18 letras. Lo mismo sucede con localization, que se abrevia “L10n”.

gettext en PHP

Existen dos formas de usar gettext en PHP: mediante la extensión gettext nativa de PHP o utilizando la librería PHP-gettext, escrita en PHP, que no necesita ninguna extensión.

La forma de usar gettext es

1
2
3
4
# @file: index.php
<?php
print _("hello world");
?>

La función_(), alias degettext(), devolverá la cadena “hello world” en el lenguaje correspondiente, de acuerdo al locale que hayamos seleccionado.

Si ejecutamos el script obtendremos “hello world” como salida, puesto que no hemos indicado ningún locale, ni creado ningún catálogo de traducción. Necesitamos crear el archivocomments.pocon la traducción de la cadena “hello world”. Esto puede hacerse mediante el comandoxgettext, o mediante un editor gráfico como poEdit.

apt-get install poedit

Creación del catálogo con poEdit

Ante todo debemos saber que la estructura de directorios para guardar los distintos catálogos tiene forma determinada. Por cada traducción se utiliza un directorio. Este generalmente se nombra usando dos letras minúsculas para el idioma, un guión bajo y dos mayúsculas para el país (es_AR, para español de Argentina). Dentro de este directorio debe existir otro con el nombre LC_MESSAGES, el cual será finalmente el directorio que contendrá el catálogo.

La estructura de nuestro ejemplo será

.
|-- locale
|   `-- es_AR
|       `-- LC_MESSAGES
|           |-- messages.mo
|           `-- messages.po
`-- index.php

El archivomessages.moes la versión compilada demessages.poy el que usará PHP para obtener la traducción.

Iniciemos poEdit. La primera vez nos preguntará por nuestro nombre y correo electrónico. Estos datos servirán para saber quién fue el último traductor que modificó el catálogo. Una vez en la ventana principal vamos a File -> New catalog. Seleccionamos el idioma (Español en este caso), el país y el código de caracteres tanto para el catálogo como para la fuente de datos desde la que obtendremos el listado de cadenas que requieren traducción. En la solapa Paths debemos colocar en ‘Base path’ la ruta completa al directorio base de archivos php (conteniendo las cadenas mencionadas anteriormente) y, debajo, en el cuadro ‘Paths’ agregar una entrada con ‘.’ indicando que se debe utilizar el directorio ingresado anteriormente. Al hacer click en OK aparecerá un cuadro de diálogo para guardar el nuevo catálogo. Navegamos hasta el directorio LC_MESSAGES y guardamos el archivo como messages.po. poEdit escaneará el directorio ingresado en Paths y extraerá todos las cadenas gettext. Ahora queda simplemente realizar la traducción y guardar el archivo. Al guardarlo, poEdit lo compilará y generará el .mo que finalmente usará PHP.

Ahora, modificaremos index.php para setear el locale

1
2
3
4
5
6
7
8
9
10
11
12
13
# @file: index.php
<?php
$language = 'es_AR.UTF-8';
putenv("LANG=$language");
setlocale(LC_ALL, "");

$domain = "messages";
bindtextdomain($domain, "./locale");
bind_textdomain_codeset($domain, 'UTF-8');
textdomain($domain);

print _("hello world");
?>

Aun nos queda un paso y es comprobar que tengamos dicho locale habilitado en nuestro sistema. Esto lo hacemos mirando la salida de

locale -a

Si no tenemos habilitado el charset es_AR.UTF8, ejecutamos

locale-gen es_AR.UTF-8

En este punto la salida del script debería ser la traducción que hicimos al español.

Tip

Para casos en que la cadena a traducir contenga variables, podemos utilizar esta función:

1
2
3
4
5
6
7
8
9
10
function __($string)
{
    $arg = array();
    for($i = 1 ; $i < func_num_args(); $i++)
        $arg[] = func_get_arg($i);
    return vsprintf(gettext($string), $arg);
}

$total = 400;
print __("results %d - %d of about %d", 1, 20, $total);

La traducción podría quedar

resultados %d - %d de aproximadamente %d

Tags: , , ,

Compilar Kernel generando paquete .deb

Aquí se describe cómo compilar un Kernel en Debian Etch, generando un.debque luego podrá ser instalado usandodpkg -i.

Paquetes requeridos para la compilación

apt-get update && \
apt-get install kernel-package libncurses5-dev fakeroot \
wget bzip2 build-essential

Descarga de código fuente desde kernel.org

cd /usr/src
wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.25.6.tar.bz2

Desempaquetado

tar xjf linux-2.6.25.6.tar.bz2

Copia del archivo de configuración del kernel actual como base para el nuevo kernel

cp /boot/config-`uname -r` /usr/src/.config

Eliminación de cualquier rastro de compilación anterior

cd linux-2.6.25.6
make clean && make mrproper

Creación link simbólico a .config (por si repetimos la compilación)

ln -s /usr/src/.config /usr/src/linux-2.6.25.6/.config

Selección de opciones, cargando .config desde la opción ‘Alternate Configuration File’.

make menuconfig

Compilación

make-kpkg clean
fakeroot make-kpkg --initrd --append-to-version=-custom kernel_image kernel_headers

Instalación

dpkg -i linux-image-2.6.25.6-custom_2.6.25.6-custom-10.00.Custom_i386.deb
dpkg -i linux-headers-2.6.25.6-custom_2.6.25.6-custom-10.00.Custom_i386.deb

Tags:

Renombrar recursivamente archivos y directorios

El siguiente script de bash renombra archivos y directorios convirtiendo sus nombres a minúsculas, reemplazando espacios, acentos, eñes y eliminando paréntesis.

Por defecto renombra únicamente aquellos archivos y directorios ubicados en el directorio pasado como parámetro. Es posible usar la opción-r|--recursivepara que trabaje recursivamente en todos los directorios hijos:

./rename.sh -r dir

Usando la opción-v|--verbosees posible ver en pantalla el listado de archivos modificados

./rename.sh -v -r dir

La opción-t|--testmuestra un listado de cambios a realizar sin realizar ninguno

./rename.sh -t -r dir

Ejemplo

xleo@calcifer:/tmp/music$ rename -t -r .
/tmp/music/Jaime Roos/1998 - Concierto Aniversario
./17 - Amándote.mp3 ./17_-_amandote.mp3
./02 - Victoria Abaracón.mp3 ./02_-_victoria_abaracon.mp3
./12 - Nadie Me Dijo Nada.mp3 ./12_-_nadie_me_dijo_nada.mp3
./16 - Durazno Y Convención.mp3 ./16_-_durazno_y_convencion.mp3
./01 - Si Me Voy Antes Que Vos-1.mp3 ./01_-_si_me_voy_antes_que_vos-1.mp3
./03 - El Hombre De La Calle.mp3 ./03_-_el_hombre_de_la_calle.mp3
./05 - Las Luces Del Estadio.mp3 ./05_-_las_luces_del_estadio.mp3
./07 - Piropo.mp3 ./07_-_piropo.mp3
./10 - Esta Noche.mp3 ./10_-_esta_noche.mp3
./06 - Se Va La Murga.mp3 ./06_-_se_va_la_murga.mp3
./08 - Los Futuros Murguistas.mp3 ./08_-_los_futuros_murguistas.mp3
./15 - Tal Vez Cheché.mp3 ./15_-_tal_vez_cheche.mp3
./13 - Bienvenido.mp3 ./13_-_bienvenido.mp3
./1998 - Concierto Aniversario.m3u ./1998_-_concierto_aniversario.m3u
./09 - Los Olímpicos.mp3 ./09_-_los_olimpicos.mp3
./11 - Cometa De La Farola.mp3 ./11_-_cometa_de_la_farola.mp3
./04 - Cuando Juega Uruguay.mp3 ./04_-_cuando_juega_uruguay.mp3
./14 - El Tambor.mp3 ./14_-_el_tambor.mp3
/tmp/music/Jaime Roos
./1998 - Concierto Aniversario ./1998_-_concierto_aniversario
/tmp/music
./Jaime Roos ./jaime_roos

rename.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/bin/bash
#
# @autor   Leonardo Vidarte
# @version $Id rename.sh 5 2008-06-05 15:44:45Z xleo $
#


# ********
# INIT SET
# ********
verbose=0
recursive=0
MOVE=/bin/mv
ECHO=


# ****
# HELP
# ****
help () {
cat << END
Usage : rename [-t] [-v] [-r] directory

Options:
  -v, --verbose    verbose move
  -r, --recursive  recursive rename
  -t, --test       don't move, only show change list. Implies -v.
  -?, --help       show this help

END

}


# ***************
# RENAME FUNCTION
# ***************
rename () {
   
    find -maxdepth 1 | \
    awk '{out=tolower($0); \
    gsub(" ?\& ?","_y_",out); \
    gsub("\(|\)","-",out); \
    gsub("[\340-\345]","a",out); \
    gsub("\347","c",out); \
    gsub("[\350-\353]","e",out); \
    gsub("[\354-\357]","i",out); \
    gsub("\361","n",out); \
    gsub("[\362-\366]","o",out); \
    gsub("[\371-\374]","u",out); \
    gsub("[^0-9a-z\./_-]","_",out); \
    if ($0!=out) {print "\""$0"\" "out;}}'
| \
    xargs -r -n 2 $ECHO $MOVE

}


# *************
# MAIN FUNCTION
# *************
main () {


    # ----------------
    # Recursive rename
    # ----------------
    if [ $recursive -eq 1 ]; then

        for dir in "$1"/*
        do
            if [ -d "$dir" ]; then
                cd "$dir" && search "$dir"
            fi
        done

    fi


    # ----------------------------
    # Rename files and directories
    # ----------------------------
    if [ $verbose -eq 1 ]; then
        echo "$1"
    fi

    cd "$1" && rename


}


# ***************************
# SHOW HELP WITHOUT ARGUMENTS
# ***************************
if [ $# -eq 0 ]; then
   help
   exit 1
fi


# *********
# SHOW HELP
# *********
if [[ "$1" =~ '(-h|--help)' ]]; then
   help
   exit 0
fi


# ***************
# CHECK ARGUMENTS
# ***************
while [ $# -gt 1 ]; do

    case "$1" in

        -v|--verbose)
            verbose=1
            MOVE="$MOVE --verbose"
        ;;    
        -r|--recursive)
            recursive=1
        ;;
        -t|--test)
            verbose=1
            MOVE=
            ECHO=/bin/echo
        ;;    
        *)
            echo invalid argument $1
            help
            exit 2
        ;;

    esac

    shift

done


# ****************************************
# CHECK DIRECTORY AND INVOKE MAIN FUNCTION
# ****************************************
if [ "$1" == '.' -o "$1" == '*' ]; then
    dir=$PWD
else
    dir=$1
fi

if [ -d "$dir" ]; then
    cd "$dir"
    dir=$PWD
    cd - 1> /dev/null
    main "$dir"
    exit 0
else
    echo rename: directory not found
    exit 3
fi

Otro ejemplo

Salida de./rename -r -v /shared/music > result.txt

Tags: , , ,

mpd – Music Player Daemon

Music Player Daemon (MPD) is a music player which allows for remote access from another computer. An example is a headless computer running MPD and using one of the available front ends to control it remotely. It also makes for a good media player for desktop computers, particularly if the user either does not use or frequently restarts X.

MPD does not stream audio; all playback occurs on the server where the music files are located. The remote client controls playback from a nearby location.

MPD uses a text file as a database in which to maintain the basic music file information when it is not running. Once the daemon is started, the database is kept completely in-memory and no hard disk access is necessary to look up or search for a song. This database does not allow arbitrary files to be added; music files must be above the music root directory and are only added to the database when the update command is sent to the server.

Install:

apt-get install mpd mpc

Edit config file/etc/mpd.conf:

port            "6600"
music_directory         "~/music"
playlist_directory      "~/.mpd/playlists"
db_file                 "~/.mpd/mpd.db"
log_file                "/var/log/mpd/mpd.log"
error_file              "/var/log/mpd/mpd.error"
user                    "mpd"
bind_to_address         "192.168.0.254" #only private interface

Create dir and set own:

mkdir -p ~/music/.mpd/playlists
chown -R mpd ~/music

Create DB:

/etc/init.d/mpd restart
mpd --create-db

Add all music to playlist and… play:

mpc update
mpc add /
mpc play

References

mpd –create-db
This will start the daemon. The ‘–create-db’ argument will read the contents of the root music directory and add the Music files to a text database. You should see the list of files being added into the DB. This may take some time to complete – based on size of your music collection.
mpc update
The command used here is ‘mpc’ – not ‘mpd’. We are using a command line client now. This command scans the root music directory for updates.
mpc add /
This command will add all the files in the music directory to the current playlist. Please note that the ‘/’ here means root music directory – and not the global linux root.
mpc play
This will start playing the files in the current playlist.

Links

Tags: ,

Bash Regular Expressions

When working with regular expressions in a shell script the norm is to use grep or sed or some other external command/program. Since version 3 of bash (released in 2004) there is another option: bash’s built-in regular expression comparison operator “=~”.

Bash’s regular expression comparison operator takes a string on the left and an extended regular expression on the right. It returns 0 (success) if the regular expression matches the string, otherwise it returns 1 (failure).

In addition to doing simple matching, bash regular expressions support sub-patterns surrounded by parenthesis for capturing parts of the match. The matches are assigned to an array variable BASH_REMATCH. The entire match is assigned to BASH_REMATCH[0], the first sub-pattern is assigned to BASH_REMATCH[1], etc..

The following example script takes a regular expression as its first argument and one or more strings to match against. It then cycles through the strings and outputs the results of the match process:

#!/bin.bash

if [[ $# -lt 2 ]]; then
    echo "Usage: $0 PATTERN STRINGS..."
    exit 1
fi
regex=$1
shift
echo "regex: $regex"
echo

while [[ $1 ]]
do
    if [[ $1 =~ $regex ]]; then
        echo "$1 matches"
        i=1
        n=${#BASH_REMATCH[*]}
        while [[ $i -lt $n ]]
        do
            echo "  capture[$i]: ${BASH_REMATCH[$i]}"
            let i++
        done
    else
        echo "$1 does not match"
    fi
    shift
done

Assuming the script is saved in “bashre.sh”, the following sample shows its output:

# sh bashre.sh 'aa(b{2,3}[xyz])cc' aabbxcc aabbcc
regex: aa(b{2,3}[xyz])cc

aabbxcc matches
  capture[1]: bbx
aabbcc does not match

Tags: , ,

Chrooted SSH/SFTP Tutorial (Debian Etch)

1. Install The Chrooted OpenSSH

First we install some prerequisites:

apt-get install libpam0g-dev openssl libcrypto++-dev libssl0.9.7 libssl-dev ssh build-essential bzip2

Then we download the patched OpenSSH sources, and we configure them with/usras directory for the SSH executable files, with/etc/sshas the directory where the chrooted SSH will look for configuration files, and we also allow PAM authentication:

cd /tmp
wget http://chrootssh.sourceforge.net/download/openssh-4.5p1-chroot.tar.bz2
tar xvfj openssh-4.5p1-chroot.tar.bz2
cd openssh-4.5p1-chroot
./configure --exec-prefix=/usr --sysconfdir=/etc/ssh --with-pam
make
make install

2. Create The Chroot Environment

Next I create a chroot environment under/home/chroot. This is the directory that all chrooted SSH users will get jailed in, i.e. they will not be able to see any files/directories outside/home/chroot.

I have to create some directories in/home/chroot, and I have to copy a few binaries like/bin/bash,/bin/ls, etc. as well as the libraries on which these binaries depend into the chroot environment so that they are available to any chrooted user.

mkdir -p /home/chroot/home/
cd /home/chroot
mkdir -p usr/lib/openssh
mkdir etc
mkdir etc/pam.d/
mkdir bin
mkdir lib
mkdir usr/bin
mkdir dev
mknod dev/null c 1 3
mknod dev/zero c 1 5

chmod 666 dev/null
chmod 666 dev/zero

Now that we have created the necessary directories, we are going to copy some binaries and all the libraries on which they depend into the chroot environment. This is an excerpt of a script that I found on http://mail.incredimail.com/howto/openssh/create_chroot_env that does this. I’ve modified it a little bit:

vi /usr/local/sbin/create_chroot_env
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

APPS="/bin/sh /bin/bash /bin/cp /bin/ls /bin/mkdir /bin/mv /bin/pwd /bin/rm /bin/rmdir /usr/bin/id /usr/bin/ssh /usr/bin/scp /bin/ping /usr/bin/dircolors /usr/bin/vi /usr/bin/sftp /usr/lib/openssh/sftp-server"
for prog in $APPS;  do
        mkdir -p ./`dirname $prog` > /dev/null 2>&1
        cp $prog ./$prog

        # obtain a list of related libraries
        ldd $prog > /dev/null
        if [ "$?" = 0 ] ; then
                LIBS=`ldd $prog | awk '{ print $3 }'`
                for l in $LIBS; do
                        mkdir -p ./`dirname $l` > /dev/null 2>&1
                        cp $l ./$l  > /dev/null 2>&1
                done
        fi
done

(If you want to make more programs available to your chrooted users, just add these programs to the APPS line.)

Now we make the script executable and run it:

chmod 700 /usr/local/sbin/create_chroot_env
create_chroot_env

Next we have to copy a few additional files and libraries to the chroot jail:

cp /lib/libnss_compat.so.2 /lib/libnsl.so.1 /lib/libnss_files.so.2 /lib/ld-linux.so.2 /lib/libcap.so.1 /lib/libnss_dns.so.2 ./lib/

cp /etc/hosts etc/
cp /etc/resolv.conf etc/
cp /etc/pam.d/* etc/pam.d/
cp -r /lib/security lib/
cp -r /etc/security etc/
cp /etc/login.defs etc/

cp /usr/lib/libgssapi_krb5.so.2 usr/lib/
cp /usr/lib/libkrb5.so.3 usr/lib/
cp /usr/lib/libk5crypto.so.3 usr/lib/
cp /lib/libcom_err.so.2 lib/
cp /usr/lib/libkrb5support.so.0 usr/lib/

Then we do this:

echo '#!/bin/bash' > usr/bin/groups
echo "id -Gn" >> usr/bin/groups
touch etc/passwd
grep /etc/passwd -e "^root" > etc/passwd

You should also copy the line of the group in which you will create new users from/etc/groupto/home/chroot/etc/group. In this tutorial we will create users in the group users, so we do this:

grep /etc/group -e "^root" -e "^users" > etc/group

and restart OpenSSH:

/etc/init.d/ssh restart

3. Create A Chrooted User

Even with the chrooted SSH that we have just installed you can log in without being chrooted (which makes sense if you log in as root, for example). Now, how does the chrooted SSH decide whom to chroot and whom not? That’s easy: the chrooted SSH looks up the user who is trying to log in in/etc/passwd. If the user’s home directory in/etc/passwdhas a . (dot) in it, then the user is going to be chrooted.

This user will not be chrooted.

user_a:x:2002:100:User A:/home/user_a:/bin/bash

This user will be chrooted.

user_b:x:2003:100:User B:/home/chroot/./home/user_b:/bin/bash

Now we create the user testuser with the home directory/home/chroot/./home/testuserand the group users (which is the default group for users on Debian so you do not have to specify it explicitly):

useradd -s /bin/bash -m -d /home/chroot/./home/testuser -c "testuser" -g users testuser

Then we give testuser a password:

passwd testuser

Finally, we have to copy the line for testuser in/etc/passwdto/home/chroot/etc/passwd:

grep /etc/passwd -e "^testuser" >> /home/chroot/etc/passwd

We have already copied the users group line from/etc/groupto/home/chroot/etc/groupso we do not have to do this here again. If you create a chrooted user in another group than users, add this group to/home/chroot/etc/group:

grep /etc/group -e "^othergroup" >> /home/chroot/etc/group

Now try to log in to SSH or SFTP as testuser. You should be chrooted and not be able to browse files/directories outside/home/chroot.

Tags: ,