Skip to content

Linux Attitude

Le libre est un état d'esprit

Archive

Tag: Commande

Niveau : Star Star Star Empty Empty
Résumé : export PS1="> "

Désolé de ne pas écrire plus souvent. Et ca risque de durer encore un peu puisque je pars en vacances ...

PS veut dire prompt string. Les 4 prompt string de bash sont les chaines de caractères affichées par le shell en différentes situations. Nous allons nous intéresser à PS1 mais sachez que la suite vaut pour toutes les autres.

Exemples

Je vais faire simple : des exemples de chaînes ainsi que la capture d'écran associée, il ne vous reste plus qu'a choisir et à copier/coller dans votre .bashrc

Toutes les captures ont été faites avec les settings suivants :

  • user : peck
  • hostname : mamachine.linux-attitude.fr

Exemples unilignes

PS1Fond noir / Fond Blanc
"[\t] \[\e[01;32m\]\u\[\e[01;33m\]@\h\[\e[00m\]:\[\e[01;34m\]\w\[\e[00m\]\$ " black
white
"\[\033[01;32m\]\u@\h \[\033[01;34m\]\W \$ \[\033[00m\]" black
white
"\[\033[0;34m\][\[\033[0;31m\]$(date +%H%M)\[\033[0;34m\]]\[\033[0;34m\][\[\033[1;31m\]\u@\h:\w\[\033[0;34m\]]\[\033[1;37m\]$\[\033[0m\] " black
white
 
 

Exemples multilignes

PS1Fond noir / Fond Blanc
"\[\e]0;\u@\h \w\a\]\[\e[1;31m\]\u\[\e[1;34m\]@\[\e[0;32m\]\h \[\e[0;33m\]\w \[\e[0;31m\]$(uptime|sed -e 's/.*: \([^,]*\), \([^,]*\), \([^,]*\).*/\1 \2 \3/') \[\e[0;34m\]\D{%Y-%m-%d %H:%M:%S} \[\e[0m\]\n\$ " black
white
 
 

Exemples monochromes

PS1Fond noir / Fond Blanc
"[\t][\u@\h:\w]\$ " black
white
"\u@\h \w> " black
white
"\!|\h|$(uname -r)|\$?> " black
white
"\[\e[1;34m\]\u@\h \w>\[\e[0m\] " black
white
"\[\e]2;\u@\H \w\a\e[32;1m\]>\[\e[0m\] " black
white
(Ici tout est dans le titre)

Faites votre choix

Cookbook

Si les exemples ne vous conviennent pas, voici un ensemble de recettes pour créer un prompt qui vous ressemble :

  • load average : "\$(cut -d ' ' -f 1-3 /proc/loadavg)"
  • uptime : "\$(uptime | cut -d, -f1 | sed -e 's/.*up//')"
  • un prompt qu'on peut copier/coller sans provoquer d'erreurs : ": <texte> ;"
  • user@host:/répertoire : "\u@\h:\w"
  • date et heure : "[\d \t]"
  • un bip à chaque ligne : "\[\a\]"
  • changer la couleur du texte (code couleur voir ci dessous) : "\[\e[<code_couleur>m\]"
  • revenir à la couleur originale du shell (en fin de ligne) : "\[\e[0m\]"
  • code de retour de la dernière commande : "-> \$?"
  • nombre de jobs mis en background par le shell : "[\j]"
  • nombre de jobs en pause : "\$(jobs | wc -l | awk '{print $1}')"
  • nombre de processus en cours d'exécution : "\$(ps ax | wc -l | tr -d ' ')"
  • afficher le tty en cours : "$(temp=$(tty) ; echo ${temp:5})"
  • chemin limité à 20 caractères : "\$(a='\w';b=\${a: -20};b=\${b:+..\$b};echo \${b:-\$a})"
  • changer le texte de titre du terminal (xterm, konsole ...) : "\[\e]0;<Texte>\a\]"
  • afficher l'état de la gestion de version en cours (voir ci dessous) : "$(__vcs_dir)"
  • afficher la sortie d'une commande : "\$(<commande>)"

Codes couleur ANSI

Il est possible d'indiquer plusieurs codes simultanément en les séparant par un ';'.

From wikipedia :

Code couleur
Code Effect Note
0 Reset / Normal all attributes off
1 Intensity: Bold
2 Intensity: Faint not widely supported
3 Italic: on not widely supported. Sometimes treated as inverse.
4 Underline: Single
5 Blink: Slow less than 150 per minute
6 Blink: Rapid MS-DOS ANSI.SYS; 150 per minute or more
7 Image: Negative inverse or reverse; swap foreground and background
8 Conceal not widely supported
21 Underline: Double not widely supported
22 Intensity: Normal not bold and not faint
24 Underline: None
25 Blink: off
27 Image: Positive
28 Reveal conceal off
30–39 Set foreground color, normal intensity 3x, where x is from the color table below
40–49 Set background color, normal intensity 4x, where x is from the color table below
90–99 Set foreground color, high intensity aixterm
100–109 set background color, high intensity aixterm
Table des couleurs
Intensité 0 1 2 3 4 5 6 7 9
Normal Black Red Green Yellow[5] Blue Magenta Cyan White reset
Brillant Black Red Green Yellow Blue Magenta Cyan White

Gestion de version

Pour que la méthode de gestion de version fonctionne, il faut ajouter le code suivant dans son .bashrc :

alias svnwdiff="svn diff --diff-cmd /home/spaillar/vimdiff-wrapper.sh"
function cvswdiff { vimdiff $1 <(cvs co -p $2 $(cat $(dirname $1)/CVS/Repository)/$(basename $1)) ;} 

function vlog { 
# cvs
cvs_log() {
   [ -d "CVS" ] || return 1
   cvs log "$@" | vim -
}

# subversion
svn_log() {
    [ -d ".svn" ] || return 1
    svn log -v "$@" | vim -
}
# git
git_log() {
    base_dir=$(git rev-parse --show-cdup 2>/dev/null) || return 1
    git log --name-status "$@" | vim -
}

git_log "$@" || svn_log "$@" || cvs_log "$@"

}

function vwdiff {
vim -c ":VCSVimDiff" $1
}

function vpull { 
# cvs
cvs_pull() {
   [ -d "CVS" ] || return 1
   cvs -q up -d
}

# subversion
svn_pull() {
    [ -d ".svn" ] || return 1
    svn up 
}
# git
git_pull() {
    base_dir=$(git rev-parse --show-cdup 2>/dev/null) || return 1
    git pull 
}

git_pull "$@" || svn_pull "$@" || cvs_pull "$@"

}



_bold=$(tput bold)
_normal=$(tput sgr0)
_yellow=$(tput setaf 3)
_green=$(tput setaf 2)

__vcs_dir() {
  local vcs base_dir sub_dir ref
  sub_dir() {
  local sub_dir
  sub_dir=$(readlink -f "${PWD}")
  sub_dir=${sub_dir#$1}
  echo ${sub_dir#/}
  }

  # git
  git_dir() {
      base_dir=$(git rev-parse --show-cdup 2>/dev/null) || return 1
      if [ -n "$base_dir" ]; then
        base_dir=`cd $base_dir; pwd`
      else
        base_dir=$PWD
      fi
      sub_dir=$(git rev-parse --show-prefix)
      sub_dir="/${sub_dir%/}"
      ref=$(git symbolic-ref -q HEAD || git name-rev --name-only HEAD 2>/dev/null)
      ref=${ref#refs/heads/}
      vcs="git"
      alias pull="git pull"
      alias commit="git commit"
      alias push="git push"
#     alias revert="svn revert"
    }

  # subversion
  svn_dir() {
      [ -d ".svn" ] || return 1
      base_dir="."
      while [ -d "$base_dir/../.svn" ]; do base_dir="$base_dir/.."; done
      base_dir=`cd $base_dir; pwd`
      sub_dir="/$(sub_dir "${base_dir}")"
      ref=$(svn info "$base_dir" | awk '/^URL/ { sub(".*/","",$0); r=$0 } /^Revision/ { sub("[^0-9]*","",$0); print r":"$0 }')
      vcs="svn"
      alias pull="svn up"
      alias commit="svn commit"
      alias push="svn ci"
      alias revert="svn revert"
    }

  # mercurial
  hg_dir() {
      base_dir="."
      while [ ! -d "$base_dir/.hg" ]; do base_dir="$base_dir/.."; [ $(readlink -f "${base_dir}") = "/" ] && return 1; done
      base_dir=$(readlink -f "$base_dir")
      sub_dir="/$(sub_dir "${base_dir}")"
      ref=$(< "${base_dir}/.hg/branch")
      hgqtop=$(hg qtop)
      if [[ $hgqtop == 'No patches applied' ]]; then 
        extra="";
      else 
        extra=" >> $hgqtop"
      fi
      vcs="hg"
  }

  # cvs
  cvs_dir() {
      [ -d "CVS" ] || return 1
      base_dir="."
      while [ -d "$base_dir/../CVS" ]; do base_dir="$base_dir/.."; done
      base_dir=`cd $base_dir; pwd`
      sub_dir="/$(sub_dir "${base_dir}")"
      vcs="cvs"
      alias pull="cvs -q up -d"
      alias commit="cvs commit"
      alias push="cvs ci"
      alias revert="cvs revert"


  }

  # hg_dir || git_dir || svn_dir || cvs_dir || base_dir="$PWD"
  git_dir || svn_dir || cvs_dir || base_dir="$PWD"
  echo "${_green}${_bold}${vcs:+($vcs)}${_yellow}${_bold}${vcs:+[$ref]}${_normal}${base_dir/$HOME/~}${_yellow}${_bold}${vcs:+${_bold}${sub_dir}${_normal}$extra}"
}

PS1='${debian_chroot:+($debian_chroot)}\u@\h:$(__vcs_dir)${_normal}\$ '

Et vous quel prompt utilisez vous ?

Niveau : Star Star Empty Empty Empty
Résumé :

Aujourd'hui nous allons mettre en valeur deux articles précédents. J'espère que vous avez déjà mis votre home sous un système de suivi de version pour suivre ses évolutions. J'ai déjà décrit à dans un article précédent. En résumé :

$ cd
$ git init
$ git add .bashrc # et tout ce que vous voulez
$ git commit

Le but étant de propager tout cela automatiquement sur différentes machines. Il est difficile de toujours penser à mettre a jour lorsqu'on fait une modification. C'est pourquoi nous allons mettre à profit l'article précédent et intercepter ssh. Grâce à cela le home de toutes nos machines seront à jour sans qu'on ait à s'en préoccuper.

Mise en place

Cette fois nous allons modifier le script en question pour lancer automatiquement une mise à jour de git de façon furtive à chaque connexion ssh. La méthode run était prévue pour :

# test permettant de savoir qu'on est bien sur le bon dépôt git pour les mises à jour (id du premier commit)
MASTER=11edf02e95ceac1fa58d4444f82f8cd4ae9c1cf5
# command tu run via the ssh socket
run()
{
    # no test if running init
    if [ "$MASTER" != "" ]
    then
        # test if distant has OUR git
        ssh -S "$1" XXX '[ -e /usr/bin/git ] && [ -d .git ] && git rev-list --reverse master 2>/dev/null | head -1' | grep "$MASTER" > /dev/null
    else
        ssh -S "$1" XXX '[ -e /usr/bin/git ]'
    fi
    if [ $? -eq 0 ]
    then
        # if yes push updates
        tmp=$(mktemp ~/.sshgit.XXXXXX)
        echo "#!/bin/sh" > $tmp
        echo "exec ssh -S $1 \"\$@\"" >> $tmp
        chmod +x $tmp
        GIT_SSH=$tmp git push --all ssh://XXX/~ > /dev/null 2> /dev/null
        rm -f $tmp
        ssh -S "$1" XXX 'git checkout -f > /dev/null'
    fi
}

De plus j'ai ajouté un paramètre spécial permettant d'initialiser le dépôt de la machine en face. En effet, on ne va pas forcer la mise à jour si le home en face n'a pas de dépôt, il se peut que l'utilisateur ne le veuille pas. C'est aussi pour ce qu'on vérifie que le dépôt git utilisé contient bien le bon commit initial.

            ssh -S "$2" XXX '[ -e /usr/bin/git ] && [ ! -d .git ] && git init > /dev/null'

Le script complet.

Usage

Pour que ça fonctionne on ajoute un alias et tant qu'à faire, on ajoute le script au dépôt :

$ alias ssh='~/.sshgit' # à mettre aussi dans le .bashrc
$ git add .sshgit
$ git commit

Et maintenant on initialise la machine en face :

$ ssh -= autremachine.net

Et voila, tout ssh ultérieur résultera en un git push suivi d'un git checkout, plus besoin de réfléchir. Ce qui veut dire qu'au fur et à mesure de vos ssh votre home se propagera un peu partout, que le réseau où vous êtes soit privé ou non car c'est la connexion normale du ssh qui est empruntée. Reste juste à faire un ssh de temps en temps un peu partout pour mettre à jour :-)

Autre

Si vous n'avez pas git sur toutes les machines, vous pouvez aussi utiliser autre chose pour synchroniser automatiquement vos home. rsync par exemple (regardez l'option -u pour les mises à jour) ou scp.

Mais pour le coup je vous laisse écrire la méthode :)

Niveau : Star Star Star Star Empty
Résumé :alias ssh='ssh macommande && ssh'

Aujourd'hui interceptons les commandes ssh. Alors ne commencez pas à penser que je suis passé du côté obscur de la force. Il y a des usage bien pratique ce script et je vous en proposerai un dans le prochain article.

Tout d'abord le problème : on veut pouvoir intercepter une commande ssh de façon silencieuse pour pouvoir utiliser la connexion qui va s'établir et lancer les commandes qu'on veut sur la machine distante. Cela implique une acceptation implicite de l'utilisateur puisqu'on va utiliser un simple alias pour "intercepter" la commande. Bien sûr rien ne vous empêche de modifier l'alias d'un ami selon les moyens qui sont à votre disposition ;-)

Principe de fonctionnement

Vous vous dites qu'il suffit de reprendre les paramètres de la commande et de la relancer. Non, habitués que vous êtes à l'agent ssh, vous avez oublié qu'en son absence l'utilisateur devra taper un mot de passe pour que la commande passe.

Pour récupérer la connexion ssh, openssh met à notre disposition tout ce qu'il faut. L'option s'appelle ControlMaster, elle crée une socket sur laquelle ssh peut ensuite se connecter pour ouvrir un nouveau terminal sans repasser toute la chaine de connexion au serveur.

La méthode est donc fait simple :

  • on intercepte la commande ssh (alias)
  • on lance notre script en background ($0 &)
  • on ajoute un option -M et -S si besoin à la commande ssh pour créer la socket
  • on garde les options originales et le processus original (exec ssh -M -S "$@")
  • dans le script en background on peut ensuite utiliser directement la socket en question pour faire ce qu'on veut

Résultat

Donc résumons : un alias

alias ssh='~/.sshalias'

Et un script nommé ~/.sshalias (commentaires en anglais par habitude). Modifiez la commande run pour metre ce que vous voulez dedans

#!/bin/sh

# GPLv2 
# author : peck

#  command tu run via the ssh socket
run()
{
        # example ssh command
        ssh -S "$1" XXX 'hostname'
}

# test if we are the child which can connect via the master
if [ "$1" == "-=0" ]
then
    go=0
    # limit to 60 retries x 1s
    for i in $(seq 1 60)
    do
        sleep 1
        # try to connect via master
        ssh -S "$2" -O check xxx 2>/dev/null
        if [ $? -eq 0 ]
        then
            go=1
            break
        fi
    done
    # run the stealth command
    if [ $go -eq 1 ]
    then
        sleep 1 # bug if we go too fast
        run "$2"
    fi
    # remove master socket if we created it
    if [ "$3" == "0" ]
    then
        rm -f "$2"
    fi
    exit 0
fi

# we are in a real ssh command
master=0
sock=""
for i in "$@"
do
    # test if master is already provided
    if [ "$i" == "-M" ]
    then
        master=1
    fi
    # retrieve socket if provided
    if [ "$i" == "-S" ]
    then
        sock=".";
    fi
    if [ "$i" == "." ]
    then
        sock="$i"
    fi
done

# create socket name if needed
if [ "$sock" == "" ]
then
    sock=$(mktemp -u -t sshx.XXXXXX)
fi

# launch child which will use our master socket
$0 -=0 "$sock" "$master" &

# run original command adding a master socket
if [ $master -eq 1 ]
then
    exec ssh "$@"
else
    exec ssh -S "$sock" -M "$@"
fi

Niveau : Star Star Empty Empty Empty
Résumé : perl -0777pe ; ps kstart_time ; stty -echo ; expr ; bc -l ; tar c - | ssh tar x -

Petite pause.

Appliquer une expression régulière en une seule fois sur tout un fichier (comme s'il ne faisait qu'une ligne) :

$ perl -0777pe 's/expression/remplacement/'

Connaitre les processus qui sont lancés "en ce moment", par exemple pendant un script d'installation :

# listes les processus par date de création toutes les 2s
$  watch "ps kstart_time aux |tail"

Éviter d'afficher les mots de passe lorsque vous les demandez à l'utilisateur dans vos scripts shell :

$ stty -echo
$ read password
$ stty echo

Faire un calcul en ligne de commande (installé partout, même sur les vieux unix) :

$ expr 1 + 5

Faire un calcul en ligne de commande, mais en mieux :

# à mettre dans votre bashrc de préférence
$ bcl() { echo "scale=2; $@" | bc -l ; }
$ bcl 1+2

Tar over ssh (rsync quoi) :

$ tar cf - /repertoire | ssh mamachine.net "cd /destination && tar xvf -"

Niveau : Star Star Empty Empty Empty
Résumé : moreutils ; ts ; vidir ; mispipe ; isutf8 ; lckdo ; vipe ; ifdata ; pee

Ces commandes sont dans le paquet moreutils sur debian.

Ajouter un timestamp sur chaque ligne pour lire une commande un peu lente :

$ ./commande | ts | tail

Éditer en masse les entrées d'un répertoire (pour renommer des images par exemple) :

# Tout le répertoire
$ vidir repertoire
# Seulement les images 
$ vidir *.jpg

Retourner le code d'erreur du premier élément d'un pipe et non du dernier (très utile en scripting) :

# Retourne une erreur si $dir n'existe pas
$ mispipe "ls $dir" "tail"

Vérifier qu'un fichier utf8 est valide :

$ isutf8 fichier && echo OK || echo "Not OK" 

Ne pas écraser un fichier de destination avant la fin de la commande :

# Version fonctionnelle de cat a b > a
$ cat a b | sponge a

Créer un script de type cron avec un lock sans effort :

$ lckdo -W 10 /var/lock/mylock /usr/local/bin/myscript

Éditer le contenu d'un pipe (très pratique pour le debug de script) :

$ commande1 | vipe | commande2

Éviter les envois de mail de rapport lorsqu'il n'y a rien à rapporter :

$ /usr/local/bin/rapport.pl | ifne mail -s "Synchro en retard" sysadmins@mynnet.net

Permettre (optionnelle ment) de passer des fichiers compressés en argument à un script (comme pour zless) :

# Recoder zless
$ zrun less $1

Éviter de parser le résultat de ifconfig ou de ip dans un script (nombreuses options, de sortie, lire le man) :

# Afficher le nombre d'octets reçus
$ ifdata -sib eth0

Passer le résultat d'une commande à plusieurs autres

# Attention si commande1 et commande2 produit du texte, rien ne garantit leur ordre
$ commande | pee "commande1" "commande2"

Comparer ligne par ligne deux fichiers avec des opérateurs plus évolués que comm :

$ combine fichier1 xor fichier2

Niveau : Star Star Star Empty Empty
Résumé : ps ; top ; htop ; atop ;

Suite à un article sur les processus, j'ai trouvé une excellente série d'article vous permettant de découvrir le fonctionnement interne du noyau sur les processus et la mémoire :

Maintenant, essayons de résumer la gestion des processus d'un point de vue utilisateur et développeur.

Naissance, vie et mort d'un processus

Un processus est créé lorsque l'appel système fork est appelé et seulement dans ce cas. Les autres méthodes possibles se basent toutes sur fork (et clone, mais il ne faut pas le dire). Fork ne fait qu'une chose (et il le fait bien), il duplique un processus existant, entièrement, à l'identique, y compris ses droits.

Ensuite, durant sa vie un processus peut être modifié de nombreuses façons :

  • Changement d'utilisateur
  • Changement de code
  • Changement de père
  • Changement de priorité
  • etc.

Enfin un processus meurt dans 2 cas :

  • Il se termine tout seul comme un grand (appel système exit)
  • Il reçoit un signal qui lui est fatal

Informations sur un processus

Informations générales

Pour récupérer des informations sur un processus vous disposez de plusieurs commandes. Ces commandes ou toutes pour source /proc/<pid> qui est un répertoire virtuel peuplé directement par le noyau.

Les commandes les plus courantes sont :

  • ps : liste des processus et de leurs caractéristiques
  • htop : liste dynamique des processus et de ce qu'ils consomment
  • pgrep : récupération d'une liste de processus par expression régulière
  • pidof : récupération du pid d'un processus recherché
  • fuser : informations sur les file descriptor d'un processus
  • lsof : idem
  • pmap : afficher le mapping mémoire d'un processus
Données sur l'activité

Un processus a une activité somme toute limitée, c'est pourquoi il est parfaitement faisable de tout tracer. Le plus évident est de tracer les appels système, mais cela ne révèle que ses interactions avec le reste du monde. Il est aussi possible de tracer les appels de fonctions voire chacune des instructions.

  • strace : liste les appels système du processus
  • ltrace : liste les appels de fonction de bibliothèques dynamiques (.so) du processus
  • pstack : affiche la pile d'appel du processus
  • gdb : avec gdb on peut tout savoir et même modifier l'action d'un processus. gdb utilise l'appel système ptrace pour cela.

Agir sur un processus

Les actions sur un processus peuvent être effectuées par plusieurs entités :

  • Le processus lui -même
  • Le processus père du processus
  • Un autre processus ayant les droits pour effectuer une action (c'est-à-dire même propriétaire ou root ... en l'absence de patch sur le noyau)

Les actions qu'on peut effectuer sur un processus sont toutes liées à un appel système. En général il existe une commande shell fournissant une fonctionnalité équivalente.

Envoi d'un signal

Les signaux permettent de communiquer de façon basique avec un processus. Il peuvent être envoyé par un autre processus ou par le noyau. man 1 kill vous indique la liste des signaux et l'action par défaut associée pour les processus qui ne les surchargent pas.

Pour envoyer un signal à un processus il existe plusieurs commandes (qui utilisent toutes l'appel système kill) :

  • kill : envoyer un signal à un processus connaissant son pid
  • killall : envoie un signal à tous les processus portant un certain nom
  • pkill : envoie un signal aux processus matchant une expression régulière
  • ctrl-z : envoie le signal STOP au processus en avant plan du shell en cours
  • fg, bg : envoie le signal CONT à un processus stoppé du shell en cours
Répartir les tâches

Les processus peuvent être plus ou moins consommateurs de ressource processeur. La partie du noyau nommée ordonnanceur (scheduler) s'occupe d'allouer ces ressources aux différents processus.

Pour influencer l'activité de l'ordonnanceur, il existe plusieurs méthodes. Tout d'abord chaque processus dispose d'une priorité, le niveau de nice. Pour altérer son propre niveau, il y a l'appel système nice qui a donné la commande nice. Pour altérer celui d'un autre processus il y a l'appel système setpriority qui a donné la commande renice.

L'ordonnanceur a la charge de répartir l'activité de plusieurs processus, de plus en plus souvent entre plusieurs processeurs. Il est possible d'influencer la répartition des processus entre processeurs avec la commande taskset (utilisant l'appel système sched_setaffinity). Cette commande permet de limiter un processus à un ou plusieurs processeurs donnés.

Il existe aussi avec CFS, un moyen de contrôler finement le temps alloué à chaque processus à travers /sys/kernel/uids ou à travers les cgroups (voir Documentation/scheduler/sched-design-CFS.txt).

De plus il existe dans le noyau un deuxième ordonnanceur qui, cette fois, organise les tâches d'accès au disque. Si c'est le CFQ qui a été choisi (car il est modifiable), il est possible de l'influencer. Le grand intérêt de ceci est de limiter les processus qui pourraient phagocyter les autres en faisant énormément d'accès disque (pensez aux backups). L'appel système ioprio_set est implémenté dans la commande ionice pour gérer cette fonctionnalité. Lisez Documentation/block/ioprio.txt pour plus de détails.

Gestion des droits

Il n'est pas possible de changer les droits d'un processus de l'extérieur. Seul lui-même en est capable. Mais le mécanisme standard d'héritage lors du fork et de changement de droits lors de l'exec permet de faire tout ce qu'on veut.

Il n'existe qu'un seul cas où les droits peuvent être augmentés (en supposant l'absence de patch de sécurité spécifique) : lancer la commande exec sur un fichier disposant du bit suid (et éventuellement de capabilities).

Ensuite pour réduire ses droits, le processus peut utiliser :

  • L'appel système chroot qui a donné la commande chroot
  • L'appel système setXXuid qui est utilisé dans pam (commande login par exemple)
  • Les capabilities à travers l'appel système setcap qui permet de limiter la liste des appels systèmes disponibles pour un processus (ceci est une option du noyau)
Devenir indépendant

Un processus reçoit des signaux mortels lorsque son tty est coupé. C'est pourquoi un processus peut vouloir obtenir son indépendance.

Il appelle alors l'appel système setsid qui le détache de son terminal. De plus il crée un nouveau groupe de processus pour lui et ses fils, ce qui en pratique le détache de son père (lequel ne pourra donc plus le tuer lorsqu'il mourra).

La commande setsid fait la même chose en ligne de commande.

Limitations

Il est possible d'imposer des limitations à un processus ainsi qu'à ses fils, il existe un appel système pour cela nommée setrlimit. Bash propose une implémentation en ligne de commande pour cet appel nommée ulimit.

Les limitations incluent des limitations en nombre de fichiers ouverts, en consommation CPU, en occupation mémoire ... vous trouverez les détails dans le manuel de bash à la commande ulimit.

IPC et mémoire partagée

Une ancienne méthode chamanique utilisée pour communiquer entre processus est constituée des IPC (inter process communication). Les ipc permettent à des processus de :

  • s'envoyer des messages (appels système msgXXX)
  • poser des sémaphores, une technique de lock pour l'accès à des données (appels systèmes semXXX)
  • partager de la mémoire (appels système shmXXX)

Ces 3 catégories de méthodes génèrent des données qui sont indépendantes des processus de par le fait qu'elle sont destinées à d'autres processus. C'est pourquoi lorsqu'un processus utilisant des ipc plante, il laisse des traces dans le système. Ces traces consomment de la mémoire inutilement et parfois bloquent d'autres processus.

C'est pourquoi les commandes ipcs et ipcrm permettent de manipuler ces données de façon extérieures. Pensez à lire le manuel, c'est très court et vous pourrez en profiter pour monitorer les données en question.

Communication avec le processus

Enfin, un processus est isolé et communique avec le reste du monde de très peu de façons différentes :

  • avec des file descriptor (réseau, fichier, pipe, tty, device ...)
  • à travers la mémoire partagée et les IPC
  • avec des signaux
  • par la ligne de commande (en lecture seule)
  • et avec quelques appels système ayant une action sur le système lui-même

Niveau : Star Star Empty Empty Empty
Résumé : shutdown -[fF] ; /forcefsck ; /fastboot ; shift-g ; sudo !! ; VAR=""""

Désolé pour le peu d'articles poussés, j'ai manqué un peu de temps récemment.

Forcer le fsck au prochain boot (explication dans /etc/init.d/checkfs)

$ touch /forcefsck
# ou
$ shutdown -F

Empecher le fsck au prochain boot (explication dans /etc/init.d/checkfs)

$ touch /fastboot
# ou
$ shutdown -f

Mettre des retours à la ligne dans une variable bash :

$ VAR=$'ligne1\nligne2'
$ echo "$VAR"

Concaténer 2 chaines en bash (attention, pas d'espaces) :

$ VAR="chaine1""chaine2"$CHAINE3'chaine4'
$ echo "$VAR"

Aller à la fin d'un fichier dans less :

shift-g

Relancer la dernière commande mais en root :

$ sudo !!