Le répertoire /proc est en fait un pseudo-système de fichiers. Les fichiers dans le répertoire /proc sont un miroir du système en cours d'exécution et des processus du noyau, et contiennent des informations et des statistiques sur elles.
bash$ cat /proc/devices
Character devices:
1 mem
2 pty
3 ttyp
4 ttyS
5 cua
7 vcs
10 misc
14 sound
29 fb
36 netlink
128 ptm
136 pts
162 raw
254 pcmcia
Block devices:
1 ramdisk
2 fd
3 ide0
9 md
bash$ cat /proc/interrupts
CPU0
0: 84505 XT-PIC timer
1: 3375 XT-PIC keyboard
2: 0 XT-PIC cascade
5: 1 XT-PIC soundblaster
8: 1 XT-PIC rtc
12: 4231 XT-PIC PS/2 Mouse
14: 109373 XT-PIC ide0
NMI: 0
ERR: 0
bash$ cat /proc/partitions
major minor #blocks name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq
3 0 3007872 hda 4472 22260 114520 94240 3551 18703 50384 549710 0 111550 644030
3 1 52416 hda1 27 395 844 960 4 2 14 180 0 800 1140
3 2 1 hda2 0 0 0 0 0 0 0 0 0 0 0
3 4 165280 hda4 10 0 20 210 0 0 0 0 0 210 210
...
bash$ cat /proc/loadavg
0.13 0.42 0.27 2/44 1119
bash$ cat /proc/apm
1.16 1.2 0x03 0x01 0xff 0x80 -1% -1 ?
bash$ cat /proc/acpi/battery/BAT0/info
present: yes
design capacity: 43200 mWh
last full capacity: 36640 mWh
battery technology: rechargeable
design voltage: 10800 mV
design capacity warning: 1832 mWh
design capacity low: 200 mWh
capacity granularity 1: 1 mWh
capacity granularity 2: 1 mWh
model number: IBM-02K6897
serial number: 1133
battery type: LION
OEM info: Panasonic
bash$ fgrep Mem /proc/meminfo
MemTotal: 515216 kB
MemFree: 266248 kB
Des scripts shells peuvent extraire des données à partir de certains des fichiers de /proc. [117]
FS=iso grep $FS /proc/filesystems # iso9660
kernel_version=$( awk '{ print $3 }' /proc/version )
CPU=$( awk '/model name/ {print $5}' < /proc/cpuinfo )
if [ "$CPU" = "Pentium(R)" ]
then
lance_des_commandes
...
else
lance_autres_commandes
...
fi
vitesse_cpu=$( fgrep "cpu MHz" /proc/cpuinfo | awk '{print $4}' )
# La vitesse d'exécution actuelle (en MHz) du CPU de votre machine.
# Sur un portable, cela peut varier suivant que vous utilisez la batterie
#+ ou le secteur.
#!/bin/bash
# get-commandline.sh
# Obtient les paramètres en ligne de commande d'un processus.
OPTION=cmdline
# Identifie le PID.
pid=$( echo $(pidof "$1") | awk '{ print $1 }' )
# Récupère seulement le premier
# ^^^^^^^^^^^^^^^^^^ de plusieurs instances.
echo
echo "ID du processus de (la première instance de) "$1" = $pid"
echo -n "Arguments en ligne de commande : "
cat /proc/"$pid"/"$OPTION" | xargs -0 echo
# Formate la sortie : ^^^^^^^^^^^^^^^
# (Merci pour la correction, Han Holl !)
echo; echo
# Par exemple :
# sh get-commandline.sh xterm
fichier_dev="/proc/bus/usb/devices"
texte="Spd"
USB1="Spd=12"
USB2="Spd=480"
vitesse_bus=$(fgrep -m 1 "$texte" $fichier_dev | awk '{print $9}')
# ^^^^ s'arrête après la première correspondance.
if [ "$vitesse_bus" = "$USB1" ]
then
echo "Port USB 1.1 découvert."
# Faire quelque chose d'appropriée avec USB 1.1.
fi
Il est même possible de contrôler certains périphériques avec des commandes envoyées au répertoire /proc.
root# echo on > /proc/acpi/ibm/light
Ceci active Thinklight sur certains modèles Thinkpad d'IBM/Lenovo. (Cela pourrait ne pas fonctionner sur toutes les distributions Linux.)
Bien sûr, vous devez faire particulièrement attention quand vous écrivez dans /proc.
Le répertoire /proc contient des sous-répertoires avec des noms numériques inhabituels. Chacun de ces noms correspond à un numéro de processus d'un processus en cours d'exécution. À l'intérieur de ces sous-répertoires, il existe un certain nombre de fichiers contenant des informations sur le processus correspondant. Les fichiers stat et status maintiennent des statistiques sur le processus, le fichier cmdline contient les arguments de la ligne de commande avec lesquels le processus a été appelé et le fichier exe est un lien symbolique vers le chemin complet du processus. Il existe encore quelques autres fichiers, mais ceux-ci sont les plus intéressants du point de vue de l'écriture de scripts.
Exemple 29.3. Trouver le processus associé à un PID
#!/bin/bash
# pid-identifier.sh
# Donne le chemin complet du processus associé avec ce pid.
NBARGS=1 # Nombre d'arguments que le script attend.
E_MAUVAISARGS=65
E_MAUVAISPID=66
E_PROCESSUS_INEXISTANT=67
E_SANSDROIT=68
PROCFILE=exe
if [ $# -ne $NBARGS ]
then
echo "Usage : `basename $0` PID" >&2 # Message d'erreur >stderr.
exit $E_MAUVAISARGS
fi
nopid=$( ps ax | grep $1 | awk '{ print $1 }' | grep $1 )
# Cherche le pid dans l'affichage de "ps" car il est le champ #1.
# S'assure aussi qu'il s'agit du bon processus, et non pas du processus appelé
# par ce script.
# Le dernier "grep $1" supprime cette possibilité.
#
# pidno=$( ps ax | awk '{ print $1 }' | grep $1 )
# fonctionne aussi comme l'indique Teemu Huovila.
if [ -z "$nopid" ] # Si, après tous ces filtres, le résultat est une chaîne vide,
then #+ aucun processus en cours ne correspond au pid donné.
echo "Aucun processus en cours."
exit $E_PROCESSUS_INEXISTANT
fi
# Autrement :
# if ! ps $1 > /dev/null 2>&1
# then # Aucun processus ne correspond au pid donné.
# echo "Ce processus n'existe pas"
# exit $E_PROCESSUS_INEXISTANT
# fi
# Pour simplifier tout cet algorithme, utilisez "pidof".
if [ ! -r "/proc/$1/$PROCFILE" ] # Vérifiez les droits en lecture.
then
echo "Processus $1 en cours, mais..."
echo "Ne peut obtenir le droit de lecture sur /proc/$1/$PROCFILE."
exit $E_SANSDROIT
# Un utilisateur standard ne peut accéder à certains fichiers de /proc.
fi
# Les deux derniers tests peuvent être remplacés par :
# if ! kill -0 $1 > /dev/null 2>&1 # '0' n'est pas un signal mais
# ceci testera s'il est possible
# d'envoyer un signal au processus.
# then echo "PID n'existe pas ou vous n'êtes pas son propriétaire" >&2
# exit $E_MAUVAISPID
# fi
fichier_exe=$( ls -l /proc/$1 | grep "exe" | awk '{ print $11 }' )
# Ou fichier_exe=$( ls -l /proc/$1/exe | awk '{print $11}' )
#
# /proc/pid-number/exe est un lien symbolique
#+ vers le chemin complet du processus appelé.
if [ -e "$fichier_exe" ] # Si /proc/pid-number/exe existe,
then # alors le processus correspondant existe.
echo "Processus #$1 appelé par $fichier_exe"
else
echo "Processus inexistant"
fi
# Ce script élaboré peut *pratiquement* être remplacé par
# ps ax | grep $1 | awk '{ print $5 }'
# Néanmoins, cela ne fonctionnera pas...
#+ parce que le cinquième champ de 'ps' est le argv[0] du processus,
#+ et non pas le chemin vers l'exécutable.
#
# Néanmoins, une des deux méthodes suivantes devrait fonctionner.
# find /proc/$1/exe -printf '%l\n'
# lsof -aFn -p $1 -d txt | sed -ne 's/^n//p'
# Commentaires supplémentaires par Stéphane Chazelas.
exit 0
Exemple 29.4. État de la connexion
#!/bin/bash
NOMPROC=pppd # démon ppp.
NOMFICHIERPROC=status # Où chercher.
NONCONNECTE=65
INTERVALLE=2 # Mise à jour toutes les deux secondes.
nopid=$( ps ax | grep -v "ps ax" | grep -v grep | grep $NOMPROC | awk '{ print $1 }' )
# Trouver le numéro de processus de 'pppd', le 'démon ppp'.
# Doit filtrer les lignes de processus générées par la recherche elle-même.
#
# Néanmoins, comme Oleg Philon l'a indiqué,
#+ ceci pourrait être considérablement simplifié en utilisant "pidof".
# nopid=$( pidof $NOMPROC )
#
# Morale de l'histoire :
#+ Quand une séquence de commandes devient trop complexe, cherchez un raccourci.
if [ -z "$pidno" ] # Si pas de pid, alors le processus ne tourne pas.
then
echo "Non connecté."
exit $NONCONNECTE
else
echo "Connecté."; echo
fi
while [ true ] # Boucle sans fin, le script peut être amélioré ici.
do
if [ ! -e "/proc/$pidno/$NOMFICHIERPROC" ]
# Quand le processus est en cours d'exécution, alors le fichier "status"
#+ existe.
then
echo "Déconnecté."
exit $NONCONNECTE
fi
netstat -s | grep "packets received" # Obtenir quelques statistiques de
netstat -s | grep "packets delivered" #+ connexion.
sleep $INTERVALLE
echo; echo
done
exit 0
# De cette façon, le script ne se termine qu'avec un Control-C.
# Exercices :
# ----------
# Améliorer le script pour qu'il se termine suite à l'appui sur la touche
# "q".
# Rendre le script plus facilement utilisable d'autres façons.
En général, il est dangereux d'écrire dans les fichiers de /proc car cela peut corrompre le système de fichiers ou provoquer une erreur fatale.