kyopages/scripts/getInfo

4959 lines
194 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# shellcheck disable=SC1091,SC2009,SC2016,SC2119,SC2129
# SC1091 Not following (source)
# SC2009 Consider using pgrep instead of grepping ps output
# SC2016 Expressions don't expand in single quotes
# SC2119 Use function "$@" if function's $1 should mean script's $1 (??)
# SC2129 Consider using { cmd1; cmd2; } >> file ... (erreur détection?)
version=4.4.0
date="08/04/2018"
contact="IRC freenode.net ##sdeb ou https://framagit.org/kyodev/kyopages/issues/"
script="getInfo"
##### license LPRAB/WTFPL
# auteur: simpledeb
# contributeurs: kyodev, saiqui, naguam, agentcobra, amilcar
#####
# détecte architecture système, assign $fu_archi: 32bits, i686 | 64bits, amd64 (x86_64)
# return 1 on unknown architecture
# remarque, debian: dpkg --print-architecture affiche i386
f__architecture(){ # 14/12/2017
x_architecture=1
case "$(uname -m)" in
amd64 | x86_64 )
fu_archi="64bits, amd64 (x86_64)";;
i?86 | x86 )
fu_archi="32bits, i686";;
* )
case "$(getconf LONG_BIT)" in
64 )
fu_archi="64bits, amd64 (x86_64)";;
32 )
fu_archi="32bits, i686";;
*)
return 1
esac ;;
esac
}
# shellcheck disable=SC2034
# SC2034 foo appears unused. Verify it or export it.
f__color(){ # 01/03/2018
if type -p tput &>/dev/null && tput setaf 1 &>/dev/null; then
BLACK=$( tput setaf 0 )
RED=$( tput setaf 1 ) # alerte
GREEN=$( tput setaf 2 ) # ok
YELLOW=$( tput setaf 3 ) # question
BLUE=$( tput setaf 4 ) # info
CYAN=$( tput setaf 6 )
MAGENTA=$( tput setaf 5 )
STD=$( tput sgr0 ) # retour "normal"
BOLD=$( tput bold )
ITAL=$( tput sitm )
SOUL=$( tput smul )
else
YELLOW=$( echo -n "\033[0;33m" ) # ?
GREEN=$( echo -n "\033[0;32m" ) # ok
BLUE=$( echo -n "\033[0;34m" ) # info
RED=$( echo -n "\033[0;31m" ) # alerte
COLOR=$( echo -n "\033[0m" ) # standard
STD=$( echo -n "\033[0m" ) # standard
fi
}
# $1=oui|non | clear | -tx (oui|non, réponse par défaut si entrée seule), $2=message, return 0 si oui, return 1 si non
# options: oui|non réponse par défaut, -txy timeout (sans espaces entre t et chiffres) 1 à 99s
# clear effacement ligne question/réponse
f__dialog_oui_non(){ # 05/03/2018
local param
# extraction timeout éventuel
if [[ "$1" =~ -t[0-9]{1,2} ]]; then
param=$( sed -En 's/.*(-t[0-9]{1,2}).*/\1/p' <<< "$1" )
fi
# affichage
echo -en "$BLUE$2$STD"
[[ "$1" =~ oui ]] && echo -n " [O/n] " || echo -n " [o/N] "
if [ "$param" ]; then
read "$param" -r
echo
else
read -r
fi
# réponse par défaut si saisie vide
if [[ -z "$REPLY" && "$1" =~ oui ]]; then
REPLY="oui"
elif [[ -z "$REPLY" && "$1" =~ non ]]; then
REPLY="non"
fi
# effacement éventuel ligne question/réponse
if [[ "$1" =~ clear ]]; then
tput cuu1 # une ligne plus haut
tput dl1 # efface ligne
else
echo
fi
if [[ ${REPLY,,} =~ ^ou?i?$ ]]; then
return 0
else
return 1
fi
}
# $1=-c|-l|-lc, $2 répertoire, [$3] motif exclusion sur nom fichier, affiche 0|null si répertoire inexistant
# -c: compte du nombre de fichiers dans un répertoire
# -l: liste inline des noms de fichiers seuls (sans chemin) (similaire ls)
# -lc: liste en colonne des noms de fichiers seuls (sans chemin) (similaire ls -1)
# si joker (*?) sur chemin, le motif d'exclusion ne s'applique pas à un répertoire listé, juste sur le nom du fichier
# exemple: f__dir -l $dir "lock|partial" ou "\.list"
f__dir(){ # 05/03/2017
local i=0 action="-c" stock=''
[[ "$1" =~ - ]] && action="$1" || action="-c" # si option en erreur: -c par défaut
while read -r ; do
if [[ ! "$REPLY" =~ $3 ]] || [ -z "$3" ]; then
REPLY=${REPLY#*:} # suppression du titre de répertoire listé
[ -z "$REPLY" ] && continue # ligne vide, on passe
((i++))
stock+="$REPLY "
fi
done <<< "$( ls "$2" 2>/dev/null )"
if [ "$action" == "-c" ]; then
echo "$i"
elif [ "$action" == "-l" ]; then
echo "${stock% }"
elif [ "$action" == "-lc" ]; then
stock=${stock% }
echo -e "${stock// /$'\n'}"
fi
}
# affichage $1 en rouge, $1++ optionnels en bleu, sortie script sur erreur, log $1 si $operation=upgrade
f__error(){ # 18/12/2017
local depart=1 i
echo -e "\n$RED $script $version, erreur critique: $1 $STD"
for (( i=2 ; i<=$# ; i++ )); do
echo -e " $BLUE${!i}$STD"
done
echo
[ "$operation" == "upgrade" ] && f__log "$script $version: $1"
exit 1
}
# affichage en bleu, si $1=raw pas de ligne vide à la fin, si $1=log alors uniquement $2 logué, combiné: $1="log:raw"
f__info(){ # 05/03/2018
local depart=1 i
if [[ "$1" =~ "raw" || "$1" =~ "log" ]]; then
depart=2
fi
if [[ "$1" =~ "log" ]]; then
f__log "$( sed -E 's/\\t//;s/\\n// ' <<< "$2" | xargs )"
fi
for (( i="$depart" ; i<=$# ; i++ )); do
echo -e " $BLUE${!i}$STD"
done
[[ "$1" =~ raw ]] || echo
}
# log spécifique, fichier log limité à 10000 octets, $1 message à loguer
f__log(){ # 05/03/2018
if [ -w "$script_logs" ]; then
if [ "$( stat -c %s "$script_logs" )" -ge "10000" ]; then
echo "$(date +%Y%m%d\ %H%M%S) $1" &>/dev/null > "$script_logs"
else
echo "$(date +%Y%m%d\ %H%M%S) $1" &>/dev/null >> "$script_logs"
fi
fi
}
# recherche commandes/paquets, $1 liste: cmd1|cmd2[>paquet] (séparées par espaces) ex: "gawk|mawk>gawk wget"
# si manque, return 1 & affiche commandes manquantes (si debian, ajout proposition paquet à installer)
f__requis(){ # 09/03/2018
local ENV_DEBIAN ireq table package commands command commandsMissing packagesMissing
if type -p dpkg &>/dev/null ; then
ENV_DEBIAN="oui" # debian
fi
if type -t f__info &>/dev/null; then
c_echo="f__info"
else
c_echo="echo -e" # f__info existe? sinon echo
fi
for ireq in $1; do # pour tous les composants de la liste $1
table=( ${ireq//>/ } ) # split sur > évite manip $IFS
commands=( ${table[0]//|/ } ) # split sur |
if [ "${table[1]}" ]; then
package=${table[1]}
else
package=${commands[0]} # pas de packages dans les options, donc idem commands[0]
fi
for command in "${commands[@]}"; do # pour toutes les commandes
if type -p "$command" &>/dev/null ; then
unset commandsMissing packagesMissing
break
else # inexistant
commandsMissing+="$command "
packagesMissing+="$package "
fi
done
done
# dédoublonnage & triage
commandsMissing=$( echo "$commandsMissing" | tr ' ' '\n' | sort --unique | tr '\n' ' ' )
packagesMissing=$( echo "$packagesMissing" | tr ' ' '\n' | sort --unique | tr '\n' ' ' )
# suppression éventuel espace final
commandsMissing=${commandsMissing% }
packagesMissing=${packagesMissing% }
# affichage final
if [ "$commandsMissing" ] && [ "$ENV_DEBIAN" ]; then
$c_echo "${RED}erreur critique, manquant: $STD$BOLD$commandsMissing" \
"vous devriez exécuter:$GREEN apt install $packagesMissing"
elif [ "$commandsMissing" ]; then
$c_echo "${RED}erreur critique, manquant: $STD$BOLD$commandsMissing"
fi
[ "$commandsMissing" ] && return 1 || return 0
}
# recherche paquet deb (scission f__requis), $1 liste paquets ("paquet1 paquet2"), si un paquet absent return 1
# assigne $deb_absent & $deb_present, si hors debian: return 1 mais $deb_present & $deb_absent vides
f__requis_deb(){ # 09/03/2018
local ireq
unset deb_present deb_absent
type -p dpkg &>/dev/null || return 1 # si pas dpkg, sortie return 0
for ireq in $1; do
LC_ALL=C dpkg --get-selections | grep -qE "^$ireq[[:space:]]+install" \
&& deb_present+="$ireq " || deb_absent+="$ireq "
done
deb_absent=${deb_absent% } # suppression éventuel espace final
deb_present=${deb_present% } # suppression éventuel espace final
[ "$deb_absent" ] && return 1
[ "$deb_present" ] && return 0
}
# $@=cmd à lancer en root avec su ou sudo. si $@ contient [':x:'] x=nombre de tentatives, 3 par défaut
# si sudo si possible sera utilisé.
# si su &2 redirigé sur &1
# si bash inexistant, return 2
f__sudo(){ # 06/03/2018
local nb sudo isudo options nbDefault=3
# détermination sudo possible
if sudo -v &>/dev/null && [ $EUID -ne 0 ] ; then
sudo="sudo su --preserve-environment -c "
else
sudo="su --preserve-environment -c "
fi
# extraction nb de tentatives éventuel
if [[ "$*" =~ :.{1,2}: ]]; then
nb="$*"
nb=${nb#*:}
nb=${nb%:*}
options=${*//:$nb:/ }
(( nb+1 )) 2>/dev/null || nb="$nbDefault" # test si numérique, sinon,
else
nb="$nbDefault"
options="$*"
fi
# lancement cmds
if [[ "$sudo" =~ ^sudo ]]; then
$sudo "$options"
else
for (( isudo=1 ; isudo<="$nb" ; isudo++ )); do
echo -en "\n[su] Mot de passe root : "
$sudo "$options" 2>/dev/null && break
[ "$isudo" == "$nb" ] && return 1
done
echo
fi
}
# test connectivité ping, $1=-4|-6, par défaut -4, return 1 si échec
f__test_cnx(){ # 08/03/2018
local proto="-4" cmd_ping iip timeout
declare -a ping_test
if [ "$1" == "-6" ]; then
proto="-6"
ping_test=(
2001:41d0:2:73d4::100 # ns10.fr.dns.opennic.glue
2a00:6d40:60:6a7f::1 # ns1.tus.it.dns.opennic.glue
2001:41d0:302:2100::949 # ns1.hau.fr.dns.opennic.glue
2001:910:800::12 # ns0.fdn.fr
2001:67c:2178:8::16 # conncheck.opensuse.org
2001:910:800::40 # ns1.fdn.fr
)
#~ [ -h "$( type -p ping6 2>/dev/null )" ] && cmd_ping="ping -6" || cmd_ping="ping6"
else
ping_test=(
51.254.141.22 # ns1.hau.fr.dns.opennic.glue
94.177.171.127 # ns1.tus.it.dns.opennic.glue
87.98.175.85 # ns10.fr.dns.opennic.glue
80.67.169.12 # ns0.fdn.fr
195.135.221.140 # conncheck.opensuse.org
80.67.169.40 # ns1.fdn.fr
)
#~ [ -h "$( type -p ping4 2>/dev/null )" ] && cmd_ping="ping -4" || cmd_ping="ping4"
fi
for timeout in 1 0; do # 2 passes, timeout 1s, si fail, timeout standard
cmd_ping="ping -c1 -w$timeout"
for iip in "${ping_test[@]}"; do
if eval "$cmd_ping" "$iip" &>/dev/null ; then
return 0 # sortie quand ok
break 2
else
echo -e "\t ip de test connectivité en échec ($iip)" 1>&2
fi
done
done
return 1 # sortie en échec
}
# $1=NOM de la variable à trimer (variable et non $variable), [$2=left|right|all], all si vide
# gain vitesse en test: 40 à 75% par rapport à '| xargs'
# var=$( function ) presque 2x lent que eval "var="
f__trim(){ # 07/03/2018
local trim=${!1}
[[ "$2" == right || "$2" == all || -z "$2" ]] && trim="${trim%${trim##*[^[:space:]]}}" # fin right
[[ "$2" == left || "$2" == all || -z "$2" ]] && trim="${trim#${trim%%[^[:space:]]*}}" # début left
eval "$1=\"$trim\""
}
# $1 chaîne où convertir les unités
f__unit_french(){ # 08/03/2018
local display
display=${1//G/Go}
display=${display//M/Mo}
display=${display//K/ko}
echo "$display"
}
# $1=nombre à convertir en ko, affiche ko ou Mo ou Go
f__unit_human(){ # 05/03/2018
echo -n "$( awk ' {
if ( $1<1024 ) {unit="ko"; printf "%d%s", $1, unit; exit}
if ( $1<1024*1024 && $1>=1024 ) {unit="Mo"; printf "%d%s", $1/1024, unit}
else {unit="Go"; printf "%.1f%s", $1/1024/1024, unit}
}' <<< "$1" )"
}
# user ayant initié la session graphique, assigne $fu_user
# return 1 sur échec identification user, return 2 sur absence home/
# gestion variable environnement user avec: USER_INSTALL=<user> script
f__user(){ # 08/03/2018
local user userid root_login
root_login="$(grep ':0:' /etc/passwd | cut -d':' -f1)" || root_login="root"
if [ "$USER_INSTALL" ]; then # user via variable environnement, moyen d'injecter root si pb
fu_user="$USER_INSTALL";
return 0
elif [[ "$TERM" =~ linux ]]; then #debian 9 recovery ou nomodeset TERM=linux
if [ "$USER" ]; then
user="$USER"
elif [ "$EUID" -eq 0 ]; then
fu_user="$root_login"
return 0
fi
fi
if [ "$SUDO_UID" ]; then
userid="$SUDO_UID";
elif grep -qEo '[0-9]+' <<< "$XDG_RUNTIME_DIR" ; then
userid=$( grep -Eo '[0-9]+' <<< "$XDG_RUNTIME_DIR" | cut -d'/' -f4 )
else
userid=$( grep -Eo '[0-9]+' <<< "$XAUTHORITY" | cut -d'/' -f4 )
fi
[ "$userid" ] && user=$( grep "$userid" /etc/passwd | cut -d ":" -f 1 )
if [ "$user" ] && [ "$user" != "$root_login" ]; then
fu_user="$user"
return 0
else
if [ "$SUDO_USER" ] && [ "$SUDO_USER" != "$root_login" ]; then
user="$SUDO_USER";
elif who | grep -qv 'root'; then
user=$( who | grep -v 'root' | head -n1 | cut -d ' ' -f1 ); # who | grep -v 'root' | awk 'FNR==1{print $1}'
else
user=$( grep -m1 'hourly.*get[A-Z].*\.anacrontab.*\.config/anacron/spool' /etc/crontab | cut -d' ' -f2 );
fi
fi
fu_user="$user"
[ "$fu_user" ] || return 1
[ -d "/home/$fu_user" ] || return 2
return 0
}
# $1='-l' comptage ligne dans variable $2, affiche quantité
# $1='-w' comptage dans variable $2 des mots
# $1='-wv' comptage dans variable $2, des mots $3, affiche quantité
# f__wcv -l $var ; f__wcv -w $var ; f__wcv -wv $var "mot"
f__wcv(){ # 09/03/2018
[[ "$1" =~ -l|-wv|-w ]] || echo "erreur f__wcv \$1 ($1) incorrect"
if [ "$1" == "-l" ]; then
grep -cEv '^[[:space:]]*$' <<< "$2" # (wc -l compterait 1 pour une variable vide)
elif [ "$1" == "-w" ]; then
result=$( xargs <<< "$2" | grep -o '[[:graph:]][[:blank:]][[:graph:]]' | grep -c ' ' )
[ "$result" -ne 0 ] && result=$(( result+1 ))
echo "$result"
elif [ "$1" == "-wv" ]; then
grep -o "$3" <<< "$2" | grep -c .
fi
}
# test wget, $1=url à tester, $2=''|print|loc|test
# par défaut, sortie du script (même si url testée ok) avec affichage erreur ou ok
# si $2=print affiche url testée & entêtes http & location, return 0
# si $2=loc affiche seulement location, return 0
# si $2=test return 0 si ok, return 1 si KO
f__wget_test(){ # 22/02/2018
local file_test_wget="/tmp/testWget-$script" retourWget retourHttp location
wget -Sq --timeout=5 --tries=2 --user-agent="$user_agent" --spider --save-headers "$1" &>"$file_test_wget"
retourWget="$?"
[ "$retourWget" == 1 ] && retourWget="1: code erreur générique"
[ "$retourWget" == 2 ] && retourWget="2: parse erreur (ligne de commande?)"
[ "$retourWget" == 3 ] && retourWget="3: erreur Entrée/sortie fichier"
[ "$retourWget" == 4 ] && retourWget="4: défaut réseau"
[ "$retourWget" == 5 ] && retourWget="5: défaut vérification SSL"
[ "$retourWget" == 6 ] && retourWget="6: défaut authentification"
[ "$retourWget" == 7 ] && retourWget="7: erreur de protocole"
[ "$retourWget" == 8 ] && retourWget="8: réponse serveur en erreur"
retourHttp=$( grep -i 'HTTP/' "$file_test_wget" | tr -d '\n' | xargs )
location=$( grep -i 'location' $file_test_wget | xargs )
if [ "$2" == "test" ]; then
rm -f "$file_test_wget"
# spécial maintenance frama.link, pas de redirection sur page status framalink
grep -q '303' <<< "$retourHttp" && return 1 # 303 See Other
[ "$retourWget" == "0" ] && return 0 || return 1
fi
if [ "$2" == "print" ]; then
if [ "$retourWget" != "0" ]; then
echo " erreur wget: erreur $RED$retourWget"
echo -e "$BLUE $1$STD\t$RED $retourHttp$STD"
else
echo -e "$BLUE $1$STD\t$GREEN $retourHttp$STD"
fi
fi
if [ "$2" == "print" ] || [ "$2" == "loc" ]; then
[ "$location" ] && echo -n "$YELLOW $location" || echo -n "$YELLOW no location"
echo "$STD"
rm -f "$file_test_wget"
return 0
fi
if [ "$retourWget" != "0" ]; then
rm -f "$file_test_wget"
f__error "wget, erreur $retourWget" "$1" "$YELLOW$retourHttp" "$location"
echo -e "$RED erreur wget, $retourWget \n $1 \n $YELLOW$retourHttp \n $location$STD" # pour les diags
return 1
fi
if grep -q '200' <<< "$retourHttp"; then
echo -e "$GREEN\ntout est ok, réessayer$STD\n"
fi
rm -f "$file_test_wget"
exit 0
}
f_affichage(){ # 12/03/2018
local affichage_text=" _ ___ __
__ _ ___| |_|_ _|_ __ / _| ___
/ _' |/ _ \ __|| || '_ \| |_ / _ \
| (_| | __/ |_ | || | | | _| (_) |
\__, |\___|\__|___|_| |_|_| \___/
|___/"
(( x_logo == 1 )) && return
x_logo=1
clear 2>/dev/null || tput clear 2>/dev/null
echo -e "$BLUE$affichage_text$YELLOW version $version - $date$STD\n"
}
# $1=type de titre var|cmd|sans|+:text|+:vide, $2 variable à afficher [$3 titre] [$4 commentaire]
# $1: cmd->`titre`, var->**titre**, sans: pas de titre
# :text ajouté, affiche le text en liste (avec puce)
# :vide bypass le test de contenu $2, affiche 'vide', si besoin, en liste
# passage en paramètre VARIABLE et pas $variable
# un test si variable $2 est vide est fait sauf ':vide'
# un test si variable $2 contient 'nofile' (non trouvé par f_grep_file), remplacé par 'fichier non trouvé'
# f_dspl "variable" "type" "titre" "commentaire"
f_dspl(){ # 21/02/2018
local display='' toDisplay
[ "$text" ] && echo -en "$text" >> "$file_output" # flush, avant fonction, de $text parent
unset text
[[ "$2" || "$1" =~ :vide ]] || return 0 # test si contenu dans $2 ou option :vide, sinon retour
toDisplay="$2"
[ "$toDisplay" ] || toDisplay="vide" # cas si :vide
# traitement ligne de titre
[[ "$1" =~ sans|var|cmd ]] || display=" **⚡ erreur f_dspl \$1 ($2 $3) ⚡** \n" # test $1 valide
[[ "$1" =~ "var" ]] && display="**$3**" # type var, titre en gras
[[ "$1" =~ "cmd" ]] && display="\`$3\`" # type cmd, titre entre backtick
[ "$4" ] && display+="$spc5( $4 )" # +$4 en gras avec 5 espaces insécables avant
[ "$1" != "sans" ] && display+=" \n"
[[ "$1" == "sans" && "$3$4" ]] && display+=" \n"
# traitement contenu
if [ "$toDisplay" == "nofile" ]; then # nofile renvoyé par f_grep
display+="\n* fichier non trouvé \n\n"
elif [[ "$1" =~ :text ]]; then
display+="\n* $toDisplay \n"
else
display+='``` \n'
display+="$toDisplay \n"
display+='``` \n\n'
fi
echo -en "$display" >> "$file_output"
}
# $1=variable à afficher en alerte/info, [$2 alert|info] type de message, alert par défaut
# un test si variable $1 est vide ou non est fait
f_dspl_alrt(){ # 07/03/2018
local display type
[ "$1" ] || return 0 # test si contenu dans $1
# flush, avant fonction, de $text parent
[ "$text" ] && echo -en "$text\n" >> "$file_output"
unset text
type="alert" # alert par défaut
[[ "$2" =~ info ]] && type="info"
[ "$type" == "alert" ] && display="> ↯ $1 \n\n"
[ "$type" == "info" ] && display="$1 \n\n"
echo -en "$display" >> "$file_output" # flush fonction
}
# $1=LISTE fichier(s) à grepper, [$2]: N &| novide &| notitre &| noinexist &| ligneVide &| date &| commentXY &| sources
# si aucun fichier dans la liste, retour indication: 'nofile|vide|inexistant'
# exemple cumul option: "10 novide notitre lignevide" (espace obligatoire, pas d'autre séparateur)
# /!\ protéger les chemins avec ", ex: f_grep_file "${toScrut[*]}".
# option largeur, des chiffres AU DÉBUT!
# option 'novide', pas d'indication vide
# option 'notitre', pas d'énumération de fichier greppé (destiné à un seul fichier)
# option 'noinexist', pas de titre si fichier inexistant
# option 'lignevide', pas de suppression des lignes vides
# option 'date', date de modification du fichier
# option 'commentXY', A LA FIN, commentaire supplémentaire à filtrer, ex: comment//
# option 'sources', les .sources avec largeur fixe 1ère colonne (format deb822)
# option 'sources', affiche les fichiers !(*.sources) en colonne selon leur largeur maxi
# commande de base: grep -Ersv '^#|^$' file|dossier "options"
f_grep_file(){ # 08/03/2018
local motifBase="^[[:blank:]]*#" motif file content largeur un deux trois quatre cinq six sept huit reste
local col1=0 col2=0 col3=0 col4=0 col5=0 col6=0 col7=0 col8=0 display=''
motif="$motifBase"
if [[ ! "$2" =~ lignevide ]]; then
motif+="|^[[:blank:]]*$"
fi
if [[ "$2" =~ comment ]]; then
motif+="|^[[:blank:]]*${2##*comment}" # conservation symboles de commentaires à la fin
fi
for file in $1; do
# contenu
content=$( grep -Ersv "$motif" "$file" 2>&1)
if [[ "$2" =~ ^[0-9] ]]; then # si $2 contient des chiffres: (largeur) en tête
largeur=${2%% *}
content=$( awk -v larg="$largeur" '{ printf "%-"larg"s",$1; $1=""; print $0 }' <<< "$content" )
fi
if [[ "$2" =~ sources && "$file" =~ \.sources$ ]]; then # nouveau format sources deb822
content=$( grep -Ersv "$motifBase" "$file" 2>&1) # conservation lignes vides
content=${content#$'\n'} # suppression éventuelle ligne vide au début
content=$( awk '{ printf "%-12s",$1; $1=""; print $0 }' <<< "$content" ) # largeur fixe première colonne
elif [[ "$2" =~ sources ]]; then # fichier sources.list ou autres genre fstab
content=$(
while read -r un deux trois quatre cinq six sept huit reste; do
[ ${#un} -gt "$col1" ] && col1=$(( ${#un}+1 ))
[ ${#deux} -gt "$col2" ] && col2=$(( ${#deux}+1 ))
[ ${#trois} -gt "$col3" ] && col3=$(( ${#trois}+1 ))
[ ${#quatre} -gt "$col4" ] && col4=$(( ${#quatre}+1 ))
[ ${#cinq} -gt "$col5" ] && col5=$(( ${#cinq}+1 ))
[ ${#six} -gt "$col6" ] && col6=$(( ${#six}+1 ))
[ ${#sept} -gt "$col7" ] && col7=$(( ${#sept}+1 ))
[ ${#huit} -gt "$col8" ] && col8=$(( ${#huit}+1 ))
done <<< "$content"
while read -r un deux trois quatre cinq six sept huit reste; do
printf "%-${col1}s %-${col2}s %-${col3}s %-${col4}s %-${col5}s %-${col6}s %-${col7}s %-${col8}s %s \n" "$un" "$deux" "$trois" "$quatre" "$cinq" "$six" "$sept" "$huit" "$reste"
done <<< "$content"
)
fi
if [ -d "$file" ]; then # si répertoire, ajout / final, joli
file+='/'
fi
content=${content//$file} # joli, suppression de $file dans les noms de fichiers entete grep
# mise en forme
if [[ ! "$2" =~ notitre ]]; then # titre
if [ -e "$file" ]; then
if [[ "$2" =~ "date" ]]; then
display+=" => $file, date de modification: $( date -r $file '+%d/%m/%Y %H:%M %z' ) \n"
else
display+=" => $file \n"
fi
elif [[ ! "$2" =~ "noinexist" ]]; then
if touch -c $file 2>/dev/null ; then
display+=" => $file: inexistant"$'\n\n'
else
display+=" => $file: Permission non accordée"$'\n\n'
fi
fi
fi
if [ "$content" ]; then
display+="$content"$'\n\n'
elif [[ ! "$2" =~ novide && -e "$file" ]]; then
display+=" ‣ vide"$'\n\n'
fi
done
#~ display=${display%%[[:space:]]} # suppression dernier \n
display=${display%$'\n'} # suppression dernier \n
if [ -z "$display" ]; then
display="nofile" # si display vide, inscription 'nofile'
fi
echo -en "$display"
}
f_help(){ # 03/03/2018
local ligne help=(
"-----------------------------------------------------------------------"
"${GREEN}./getInfo$STD : exécution script"
"${GREEN}getInfo$STD : exécution script installé dans le système"
" "
"$BOLD""options:$STD"
"$BLUE -c$STD : (catégorie) menu sélection catégorie d'analyse"
"$BLUE -cs$STD : catégorie système $BLUE-cs$STD : catégorie configuration"
"$BLUE -cr$STD : catégorie réseau $BLUE-ca$STD : catégorie analyse"
"$BLUE -j$STD : (journaux) analyse démarrage système, log Xorg, kernel et système, catégorie -ca"
"$BLUE -l$STD : (list) afficher le rapport markdown existant"
"$BLUE -p$STD : (paste) exporte le rapport markdown existant, durée standard du paste 7 jours"
"$BLUE -us$STD : upgrade spécial du script en place (sans être installé)"
"$BLUE --debug$STD : messages d'erreur (stderr) logués et exportés avec le rapport"
"$BLUE --ip$STD : affiche ip publique (ipv4/ipv6), pas de rapport markdown"
"$BLUE --mac$STD : affiche adresses Mac, pas de rapport markdown"
"$BLUE --rc$STD : gfetch, affiche un résumé, destiné à l'identification et appelé depuis .batchrc"
"$BLUE --serial$STD : affiche n° série disques, batterie et châssis, pas de rapport markdown"
"$BLUE --ssid$STD : affiche configurations ssid, pas de rapport markdown,$RED root & NetworkManager$STD requis"
"$BLUE -t$STD${GREEN}n$STD : durée de conservation du paste de$GREEN n$STD jour(s)"
"-----------------------------------------------------------------------"
"$BLUE./$script -i$STD : installation du script dans le système $RED(root)$STD"
"$BLUE$script -h$STD, --help : affichage aide"
"$BLUE$script --irc$STD : installation gfetch $RED(root)$STD"
"$BLUE$script -r$STD, --remove : désinstallation du script $RED(root)$STD"
"$BLUE$script --rrc$STD : désinstallation gfetch $RED(root)$STD"
"$BLUE$script -u$STD, --upgrade : mise à jour script"
"$BLUE$script -v$STD, --version : version du script"
)
tput cuu1 # une ligne plus haut
for ligne in "${help[@]}"; do
echo -e " $ligne"
done
echo -e "$STD\n plus d'infos: $GREEN$url_notice\n$STD"
}
# $1=texte à épurer
f_lifting(){ # 08/02/2018
local text="$1"
text=${text/ System Controller Hub}
text=${text/ Advanced Micro Devices, Inc.}
text=${text/ Electronics Co., Ltd.}
text=${text/ Co., Ltd.}
text=${text/ Semiconductor Co., Ltd.}
text=${text/ Semiconductor Corp.}
text=${text/ Series Family /Series}
text=${text/ Series Chipset Family /Series}
text=${text/ High Definition / HD }
text=${text/ Semiconductor}
text=${text/ Computer}
text=${text/ COMPUTER}
text=${text/ Industries}
text=${text// Limited}
text=${text//, Inc.}
text=${text//, Inc}
text=${text// Inc.}
text=${text// INC.}
text=${text// Corporation}
text=${text// Corp.}
text=${text// Co.}
text=${text//, Ltd}
text=${text//, Ltd.}
text=${text// Ltd.}
text=${text//\(R\)}
text=${text//\(TM\)}
text=${text//\(r\)}
text=${text//\(tm\)}
text=${text// / }
echo "$text"
}
# $1=preferences|sources, affiche fichiers ignorés par apt
f_policy(){ # 27/01/2018
local policy
policy=$( LC_ALL=C apt-cache --quiet=0 policy foo 2>&1 | grep 'Ignoring file' )
policy=$( awk -v motif="$1" '
$0 ~ motif { print $7$4 }
' <<< "$policy" )
policy=${policy//\'}
echo "$policy"
}
# f_prnt "1||2|3|l1|l2|l3|tit1|tit2|tit3|hl|quote|flush|code" "texte" '[CONDITION test]'
# $1: 1|2|3 indentation, liste à puce, une puce par ligne
# l1|l2|l3 ligne, indentation, avec espaces
# tit1|tit2|tit3
# quote|hl|flush
# $2 texte à afficher, pas de contrôle si texte null ou présent
# $3 test éventuel, Si CONDITION ok -> affichage
# ATTENTION aux éventuelles collision $x dans ce cas:
# "[ \"$1\" != \"notitre\" ]" ou "[ $1 != notitre ]" (attention au manque de ")
# flush (f_prnt flush) inutile si f_d(x) final
# $1 type, $2 texte, [$3] test /!\ assigne la variable parent $text
f_prnt(){ # 05/03/2018
local preline='' line='' endline=" \n"
[[ "$1" =~ tit ]] && preline="\n\n"
[[ "$1" == tit1 ]] && preline+="# "
[[ "$1" == tit2 ]] && preline+="## "
[[ "$1" == tit3 ]] && preline+="### "
[[ "$1" =~ tit ]] && endline+="\n"
[[ "$1" == 1 ]] && line="$( sed -E 's/(.*)/* \1 /' <<< "$2" )"
[[ "$1" == 2 ]] && line="$( sed -E 's/(.*)/ * \1 /' <<< "$2" )"
[[ "$1" == 3 ]] && line="$( sed -E 's/(.*)/ * \1 /' <<< "$2" )"
[[ "$1" == l1 ]] && line="$( sed -E 's/(.*)/\1/ ' <<< "$2" )"
[[ "$1" == l2 ]] && line="$( sed -E 's/(.*)/ \1/ ' <<< "$2" )"
[[ "$1" == l3 ]] && line="$( sed -E 's/(.*)/ \1/ ' <<< "$2" )"
[[ "$1" == quote ]] && preline="> "
[[ "$line" ]] || line="$2" # utilisation $2 sans traitement à faire
if [[ "$3" ]]; then
eval "$3" || return 0 # évaluation de la CONDITION, si erreur: sortie
fi
if [[ "$1" == "hl" ]]; then # <hl>
text+="\n---\n"
elif [[ "$1" == "code" ]]; then # ```
text+='```\n'
elif [[ "$1" ]]; then
text+="$preline$line$endline" # ligne formatée
else
text+="\n" # newline
fi
if [[ "$1" == "flush" ]]; then
echo -en "$text" >> "$file_output"
unset text
fi
}
# $1=file à parser, [$2=marge] margin left 2 espaces
# tout en bash regex par défaut non-greedy (non gourmand) comme sed ou awk
# contrainte markdown:
# l'italique avec _ ou * n'est pas géré, trop d'interférences potentielles
# liste niveau2: 3 ou 4 caractères, niveau3: 6 ou 8 caractères, puce * ou -
f_prnt_md(){ # 08/03/2018
local display display2 ligne margin
if [ ! -f "$1" ]; then
f__info "pas de rapport à afficher, vous devez lancer une analyse auparavant:" \
"$GREEN$script -l$BLUE ou afficher l'aide $GREEN$script -h"
return 0
fi
if [ "$( stat -c %s "$1" )" -gt 100000 ]; then # si taille en octets > 100ko pager
pager "$1" || less "$1" || more "$1"
return
fi
if [ "$2" == "marge" ]; then
margin=" "
fi
display=$( < "$1" )
# code
display=${display//\`\`\`/------------} # transforme ``` en ---, plus visibles
# traitement par lignes, à là sed, obligatoire pour les titres #
# plus simple pour les multi-patterns, sinon matches multilignes délicats à gérer en cas d'impairage
while read -r ligne; do
[[ "$ligne" == "------------" && "$operation" == "rc" ]] && continue
ligne=${ligne//\\/\\\\} # re echappement des antislash, utile pour efiboot
# # TITRE 1 red
[[ "$ligne" =~ ^(#[^#].*)$ ]] && ligne="\x1B[31m${BASH_REMATCH[1]}\x1B(B\x1B[m"
# ## TITRE 2 blue
[[ "$ligne" =~ ^(#{2}[^#].*)$ ]] && ligne="\x1B[34m${BASH_REMATCH[1]}\x1B(B\x1B[m"
# ### TITRE 3 green
[[ "$ligne" =~ ^(#{3}[^#].*)$ ]] && ligne="\x1B[32m${BASH_REMATCH[1]}\x1B(B\x1B[m"
# #### TITRE 4 yellow
[[ "$ligne" =~ ^(#{4}[^#].*)$ ]] && ligne="\x1B[33m${BASH_REMATCH[1]}\x1B(B\x1B[m"
# interne message alert, red
[[ "$ligne" =~ ( ↯ .*)$ ]] && ligne="\x1B[31m${BASH_REMATCH[1]}\x1B(B\x1B[m"
# interne message indo, green
[[ "$ligne" =~ ( ☛ .*)$ ]] && ligne="\x1B[32m${BASH_REMATCH[1]}\x1B(B\x1B[m"
# **gras**
while [[ "$ligne" =~ (.*)\*{2}(.*)\*{2}(.*) ]]; do
ligne="${BASH_REMATCH[1]}\x1B[1m${BASH_REMATCH[2]}\x1B(B\x1B[m${BASH_REMATCH[3]}"
done
# ` backtick en italique
while [[ "$ligne" =~ (.*)\`([^\`].*)\`(.*) ]]; do
ligne="${BASH_REMATCH[1]}\x1B[3m${BASH_REMATCH[2]}\x1B(B\x1B[m${BASH_REMATCH[3]}"
done
# puces niveau 1
ligne=${ligne/#\*[^*]/• }
ligne=${ligne/#-[^-]/• }
# puces niveau 2
[[ "$ligne" =~ ^([[:space:]]{3,4})\*(.*)$ ]] && ligne="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
[[ "$ligne" =~ ^([[:space:]]{3,4})-(.*)$ ]] && ligne="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
# puces niveau 3
[[ "$ligne" =~ ^([[:space:]]{6,8})\*(.*)$ ]] && ligne="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
[[ "$ligne" =~ ^([[:space:]]{6,8})-(.*)$ ]] && ligne="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
display2+="$margin""$ligne"$'\n'
done <<< "$display"
echo -e "${display2%$'\n'}"
}
# $1=modules [$2=repertoire spécifique de recherche], affiche emplacements et modules trouvés
f_search_ko(){ # 06/03/2018
local dir motif emplacement imod mod_ko
dir="/lib/modules/$( uname -r )"
if [ "$1" ]; then
motif="$1"
else
return 1
fi
if [ "$2" ]; then
dir="$2"
fi
motif="($motif|${motif//_/-})\.ko"
emplacement=$( du -a "$dir" | grep -Ew "$motif" )
if [ "$emplacement" ]; then
IFS=$'\n'
for imod in $emplacement; do
imod=${imod#*/}
mod_ko+=" => /$imod"$'\n'
done
IFS="$IFS_INI"
mod_ko=${mod_ko%[[:cntrl:]]} # suppression \n final
fi
echo -e "$mod_ko"
}
# [$1=silent], assigne fe_nb_audio, fe_cards_audio
fi_audio(){ # 06/03/2018
local cardsAudio cmd_cards version_alsa card_alsa cmd_card_alsa cmt_card_alsa pluriel text
local arecord aplay mod_alsa cmd_mod_alsa cmt_mod_alsa modAudio cmd_modAudio cmt_modAudio
local alert_alsa
x_audio=1
# devices
figet_lspci "audio" "name"
fe_cards_audio=$( f_lifting "${lspci[name]}" )
fe_cards_audio=${fe_cards_audio% controller}
fe_cards_audio=${fe_cards_audio% Controller}
fe_cards_audio=${fe_cards_audio#*: }
fe_nb_audio=${lspci[nb_card]}
[ "$fe_nb_audio" -eq 0 ] && return 0
[ "$1" == "silent" ] && return 0 # pas d'affichage
###
# lspci
figet_lspci "audio" "raw"
cardsAudio=${lspci[card]}
cmd_cards="lspci -nnv | grep -Ei -A10 'Audio device|Audio controller'"
if [ ! -d /proc/asound ] ; then
alert_alsa="/proc/asound : répertoire inexistant"
alert_alsa="ALSA n'est pas installé correctement"
else
# ALSA
version_alsa=$( awk '{
sub(/Advanced Linux Sound Architecture Driver /,"")
sub(/Version /,"")
sub(/.$/,"")
print $0
}' /proc/asound/version )
card_alsa=$( awk ' { print " "$0 }' /proc/asound/cards )
if [ "$( grep -c '\[.*\]' <<< "$card_alsa" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmd_card_alsa="cat /proc/asound/cards"
cmt_card_alsa="carte$pluriel enregistée$pluriel"
# périphériques
arecord=$( LC_ALL=C arecord -l 2>/dev/null | grep 'card' )
aplay=$( LC_ALL=C aplay -l 2>/dev/null | grep 'card' )
cmd_arecord="arecord -l | grep 'carte'"
cmd_aplay="aplay -l | grep 'carte'"
cmt_arecord="périphériques de capture"
cmt_aplay="périphériques de lecture"
# modules alsa
mod_alsa=$( awk '{ print $2 }' /proc/asound/modules )
mod_alsa=$( sort <<< "$mod_alsa" )
if [ "$( f__wcv -l "$mod_alsa" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmd_mod_alsa="cat /proc/asound/modules"
cmt_mod_alsa="module$pluriel alsa"
# modules kernel utilisé
figet_lspci "audio" "module"
modAudio="${lspci[module]}"
cmd_modAudio="lsmod | grep -Ew '${lspci[srch_mod]}'"
if [ "$( f__wcv -wv "$modAudio" "^[[:alnum:]]" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_modAudio="$( f__wcv -wv "$modAudio" "^[[:alnum:]]" ) module$pluriel utilisé"$pluriel
fi
###
f_prnt tit2 "audio"
f_prnt 1 "$( sed -E 's/(.*)/**\1** /' <<< "$fe_cards_audio" )" # en gras
f_prnt
# lspci -nnv
f_dspl cmd "$cardsAudio" "$cmd_cards"
f_dspl_alrt "$alert_alsa" "alert"
f_dspl cmd "$version_alsa" "/proc/asound/version" "driver alsa (Advanced Linux Sound Architecture)"
f_dspl cmd "$card_alsa" "$cmd_card_alsa" "$cmt_card_alsa"
f_dspl cmd "$arecord" "$cmd_arecord" "$cmt_arecord"
f_dspl cmd "$aplay" "$cmd_aplay" "$cmt_aplay"
f_dspl cmd "$mod_alsa" "$cmd_mod_alsa" "$cmt_mod_alsa"
f_dspl cmd "$modAudio" "$cmd_modAudio" "$cmt_modAudio"
}
fi_batt(){ # 06/03/2018
local pluriel
(( x_batt == 1 )) || figet_batt
[ "$fg_batt" ] || return 0 # pas de batterie
###
if [ "$fg_nb_batt" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt tit2 "batterie"$pluriel
f_dspl sans "$fg_batt"
}
# [$1=silent], assigne $fe_nb_bluez, $fe_cards_bluez
fi_bluez(){ # 06/03/2018
local bluez cmd_bluez cmt_bluez mod cmd_mod cmt_mod pluriel text
x_bluez=1
if type -p hcitool &>/dev/null ; then
fe_nb_bluez=$( hcitool dev | grep -c 'hci[[:digit:]]' )
fe_cards_bluez=$( hcitool dev | grep -Eo 'hci[0-9]+' | tr '\n' ' ' )
else
fe_nb_bluez=-99
fe_cards_bluez="n/a"
fi
[[ "$1" == "silent" || "$fe_nb_bluez" -le 0 ]] && return 0
# état
bluez=$( hciconfig -a )
if [ "$fe_nb_bluez" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmd_bluez="hciconfig -a"
cmt_bluez="état périphérique"$pluriel
# modules
figet_modules "bluetooth"
mod="$fg_modules" # modules chargés
cmd_mod="lsmod | grep -Ew '$fg_srch_mod'"
if [ "$( f__wcv -l "$mod" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_mod="$( f__wcv -l "$mod" ) module$pluriel utilisé"$pluriel
fg_mod_motif=${fg_mod_motif//|/ } # fg_mod_motif motif de recherche, avec |
###
f_prnt tit2 "Bluetooth"
f_dspl cmd "$bluez" "$cmd_bluez" "$cmt_bluez"
f_dspl cmd "$mod" "$cmd_mod" "$cmt_mod"
[ "$mod" ] || f_dspl sans "$fg_mod_motif" " " "pas de modules en mémoire parmi:"
}
fi_conf(){ # 21/02/2018
local confs appArmor toScrut=(
'/etc/default/grub'
'/etc/default/grub.d/*.cfg'
# '/etc/grub.d/' # pour info
'/etc/sysctl.conf'
'/etc/sysctl.d/*.conf'
'/etc/hostname' # debian
'/etc/sysconfig/network' # fedora?
'/etc/HOSTNAME' # suse
# /etc/os-release # nouveau standard systemd/freedesktop (voir figet_distrib)
'/etc/vconsole.conf'
# /etc/locale.conf # (voir fi_locale)
'/etc/tmpfiles.d/*.conf'
'/etc/binfmt.d/*.conf'
# /etc/machine-id # voir (fi_serial)
'/etc/modules-load.d/*.conf' #modules to load at boot time
'/etc/machine-info'
'/etc/modprobe.d/*.conf' # blacklist modules
'/etc/systemd/system/*/override.conf' # éditions services
'/etc/discover-modprobe.conf'
)
confs=$( f_grep_file "${toScrut[*]}" "noinexist" )
appArmor=$( aa-status 2>/dev/null )
###
f_prnt tit2 "configuration, divers"
f_dspl cmd "$confs" "grep -Ersv '^#|^$' <fichiers désirés>"
f_dspl cmd "$appArmor" "aa-status" "statut AppArmor"
}
fi_cpu(){ # 08/03/2018
local cpu_flags text iflag qte_flags text_flags="" pluriel
local alert_microcode
(( x_cpu == 1 )) || figet_cpu
(( x_cpu_flags == 1 )) || figet_cpu_flags # 'base' des tags
cpu_flags=$( awk -F ': ' '/^flags/ { print $2; exit }' /proc/cpuinfo | tr ' ' '\n' | sort | tr '\n' ' ' ) # vitesse, pas mieux
for iflag in $cpu_flags; do
text_flags+=$( awk -v motif="$iflag" -F '⟷' '
BEGIN { pattern = "^"toupper(motif) } # recherche sur majuscule
$0 ~ pattern { $1 = motif; exit } # $1 (flag en minuscule)
END { if( $1 != motif ) { $1 = motif; $2 = "?" } # si rien trouvé: ?
printf ("%-20s %s",$1,$2 )
}
' <<< "$CPU_FLAGS" )$'\n'
done
text_flags=${text_flags%[[:cntrl:]]} # suppression \n final
qte_flags=$( f__wcv -w "$cpu_flags" flags )
if ! figet_ucode ; then # retour fonction en erreur => pas d'installation mais possible
alert_microcode="$fg_ucode"
[ "$ENV_DEBIAN" ] && alert_microcode+="\n les installer: **apt install $ucode**"
fi
if [ $(( ${fg_cpu:0:1} )) -gt 1 ]; then pluriel="s"; else unset pluriel; fi
unset CPU_FLAGS x_cpu_flags
###
f_prnt tit2 "processeur"$pluriel
f_dspl cmd "$fg_cpu" "lscpu" # affichage proc
f_dspl var "$fg_uarch" "µ architecture processeur"
f_dspl_alrt "$alert_microcode" "info"
f_prnt 1 "$fg_ucode" '[[ -z "$alert_microcode" && "$fg_ucode" ]]'
f_prnt
f_dspl var "$cpu_flags" "$qte_flags flags cpu" # flags cpu bruts
f_dspl sans "$text_flags" # flags cpu texte
}
# shellcheck disable=SC2086
# SC2086 Double quote to prevent globbing and word splitting
# (certaines variables ne sont pas quotées pour permettre les traitements avec liste, ex: df)
fi_disk(){ # 13/03/2018
local cmd_dd_temp="" dd_temp="" liste_df disk_df disk_df_i cmd_dfi cmd_dfh disk_lsblk fstab crypttab
local resume idResume idSwap idisk text pluriel
local alert_dd_temp alert_file_resume alert_uuidResume
(( x_disk == 1 )) || figet_disk
# hddtemp
if type -p hddtemp &>/dev/null ; then
for idisk in $fg_disk_fixe; do
[ -r "/dev/$idisk" ] || continue
temp=$(( $( LC_ALL=C hddtemp -n "/dev/$idisk" 2>/dev/null ) ))
if [ "$temp" -ge 50 ]; then
alert_dd_temp+="$idisk: température > 50°C "$'\n'
fi
dd_temp+="$idisk: $temp °C"$'\n'
cmd_dd_temp+=" /dev/$idisk"
done
dd_temp=${dd_temp%$'\n'} # suppression dernier $'\n'
cmd_dd_temp="hddtemp$cmd_dd_temp"
[ "$alert_dd_temp" ] && alert_dd_temp=${alert_dd_temp::-1} # suppression dernier $'\n'
fi
# df, espaces des partitions montées seules
liste_df=$( printf "/dev/%s " $fg_disk_part_fixe_m ) # $fg_disk_part_swap
disk_df=$( df -h --total --output=source,target,fstype,size,used,avail,pcent $liste_df )
cmd_dfh="df -h --total --output=source,target,fstype,size,used,avail,pcent $liste_df"
disk_df=$( f__unit_french "$disk_df" )
# df -i, inoeuds
disk_df_i=$( df -i $liste_df )
cmd_dfi="df -i $liste_df"
# lsblk répertoire disques & partitions
disk_lsblk=$( lsblk -o NAME,FSTYPE,SIZE,LABEL,MOUNTPOINT,UUID )
disk_lsblk=$( f__unit_french "$disk_lsblk" )
# fstab & crypttab éventuel
fstab=$( f_grep_file "/etc/fstab" "sources notitre" )
crypttab=$( f_grep_file "/etc/crypttab" "sources notitre" )
# resume
resume=$( f_grep_file "/etc/initramfs-tools/conf.d/resume" "notitre" )
if [ "$resume" == "nofile" ]; then
alert_file_resume="Pas de fichier _resume_ dans /etc/initramfs-tools/conf.d/" # alert resume absent
fi
idResume=$( grep -Evs '^[[:blank:]]*#|^$' /etc/initramfs-tools/conf.d/resume | sed -En 's/.*UUID=([0-9a-Z-]*).*$/\1/p' )
idSwap=$( grep -Ev '^[[:blank:]]*#|^$' /etc/fstab | sed -En 's/UUID=([0-9a-Z-]*).*swap.*$/\1/p' )
if [ "$idSwap" ] && [ "$idResume" ] && [ "$idSwap" != "$idResume" ]; then
alert_uuidResume+="vérifier la config resume, l'UUID ne correspond pas à celui du swap. \n"
alert_uuidResume+="id swap : $idSwap \nid resume: $idResume \n"
alert_uuidResume+="vous pouvez utiliser _RESUME=auto_ ou _RESUME=/dev/sdx_ (voire supprimer ce fichier)"
fi
###
if [ "$fg_nb_disk" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt tit2 "disque"$pluriel
# espace des partitions fixes montées
f_prnt 1 "$( awk -F ': ' '{print $1": **"$2"**"}' <<< "$fg_disk_part_fix_tot" )"
f_prnt 1 "$fg_disk_part_syst"
f_prnt
f_prnt code
# disques fixes et amovibles
if [ "$( wc -w <<< "$fg_disk_fixe" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l "$( printf '%-17s: %s' "disque$pluriel fixe$pluriel" "$fg_disk_fixe" )"
if [ "$( wc -w <<< "$fg_disk_amov" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l "$( printf '%-17s: %s' "disque$pluriel amovible$pluriel" "$fg_disk_amov" )"
f_prnt
# partitions fixes montées / swap / non montées
if [ "$( wc -w <<< "$fg_disk_part_fixe_m" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l "$( printf '%-24s: %s' "partition$pluriel fixe$pluriel montée$pluriel" "$fg_disk_part_fixe_m" )"
if [ "$( wc -w <<< "$fg_disk_part_swap" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l "$( printf '%-24s: %s' "partition$pluriel swap$pluriel" "$fg_disk_part_swap" )"
if [ "$( wc -w <<< "$fg_disk_part_fixe_nm" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l "$( printf '%-28s: %s' "partition$pluriel fixe$pluriel non montée$pluriel" "$fg_disk_part_fixe_nm" )"
f_prnt
# partitions amovibles montées / non montées
if [ "$( wc -w <<< "$fg_disk_part_amov_m" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l "$( printf '%-33s: %s' "partition$pluriel amovible$pluriel montée$pluriel" "$fg_disk_part_amov_m" )"
if [ "$( wc -w <<< "$fg_disk_part_amov_nm" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l "$( printf '%-33s: %s' "partition$pluriel amovible$pluriel non montée$pluriel" "$fg_disk_part_amov_nm" )"
f_prnt
# détails des disques par type
f_prnt l "$fg_disk_table"
f_prnt code
f_prnt
if [ "$fg_nb_disk" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt 1 "**types de disque$pluriel** "
f_prnt 2 "ata : $fg_disk_ata (y compris externe ata sur usb)" '[ "$fg_disk_ata" ]'
f_prnt 2 "usb : $fg_disk_usb (type clefs usb)" '[ "$fg_disk_usb" ]'
f_prnt 2 "mmc : $fg_disk_mmc" '[ "$fg_disk_mmc" ]'
f_prnt 2 "nvme: $fg_disk_nvme" '[ "$fg_disk_nvme" ]'
f_prnt
# éventuellement hddtemp
f_dspl cmd "$dd_temp" "$cmd_dd_temp" "température disque"$pluriel
f_dspl_alrt "$alert_dd_temp" "info"
# df, espaces des partitions montées seules
f_dspl cmd "$disk_df" "$cmd_dfh" "utilisation disque"$pluriel
# df -i, inoeuds
f_dspl cmd "$disk_df_i" "$cmd_dfi" "utilisation inoeuds"
# lsblk répertoire disques & partitions
f_dspl cmd "$disk_lsblk" "lsblk -o NAME,FSTYPE,SIZE,LABEL,MOUNTPOINT,UUID" "disque$pluriel & partitions"
# fstab & crypttab
f_dspl cmd "$fstab" "grep -Ev '^#|^$' /etc/fstab" "fstab"
f_dspl cmd "$crypttab" "grep -Ev '^#|^$' /etc/crypttab" "crypttab"
# resume
f_dspl cmd "$resume" "grep -Evs '^#|^$' /etc/initramfs-tools/conf.d/resume" "resume"
f_dspl_alrt "$alert_file_resume" "info"
f_dspl_alrt "$alert_uuidResume" "alert"
}
# shellcheck disable=SC2181
# SC2181 Check exit code directly
fi_dmesg(){ # 08/03/2018
local dmesg_err dmesg_warn dmesg_crit file info_ucode alert_firmBug text nb_lignes=25
local alert_firmBug
file="/tmp/$script-dmesg"
[ "$EUID" -eq 0 ] || echo
f__sudo "dmesg -Hk --nopager -l emerg > $file-emerg ; \
dmesg -Hk --nopager -l alert > $file-alert ; \
dmesg -Hk --nopager -l crit > $file-crit ; \
dmesg -Hk --nopager -l err > $file-err ; \
dmesg -Hk --nopager -l warn > $file-warn ; \
dmesg -Hk --nopager -l info | grep -i 'microcode: .*updated early' > $file-ucode ; \
dmesg -Hk --nopager | grep -i 'Firmware Bug' > $file-firmBug ; \
chown $fu_user: $file-*"
if [ "$?" != "0" ]; then
f__info "\n les commandes$GREEN dmesg$RED ont échoué $BLUE(droits root requis, échec authentification?)" \
"vous pouvez relancer le script complet$RED en root$BLUE pour voir les erreurs du noyau via dmesg" \
"ou juste la partie journaux avec $GREEN$DIRNAME""getInfo -j"
text+="* les commandes \`dmesg\` ont échoué, relancer avec les droits root \n\n"
echo -e "$text" >> "$file_output"
return 0
fi
dmesg_emerg=$( sed -n 1,"$nb_lignes"p $file-emerg )
dmesg_alert=$( sed -n 1,"$nb_lignes"p $file-alert )
dmesg_crit=$( sed -n 1,"$nb_lignes"p $file-crit )
dmesg_err=$( sed -n 1,"$nb_lignes"p $file-err )
dmesg_warn=$( sed -n 1,"$nb_lignes"p $file-warn )
[ "$dmesg_emerg" ] || dmesg_emerg=" <vide>"
[ "$dmesg_alert" ] || dmesg_alert=" <vide>"
[ "$dmesg_crit" ] || dmesg_crit=" <vide>"
[ "$dmesg_err" ] || dmesg_err=" <vide>"
[ "$dmesg_warn" ] || dmesg_warn=" <vide>"
# messages microcode
info_ucode=$( < $file-ucode )
[ "$info_ucode" ] && info_ucode="microcode processeur mis à jour au boot"
alert_firmBug=$( < $file-firmBug )
# suppression fichier de transfert
rm "$file-"*
###
f_prnt tit2 "dmesg kernel (emergency, alerte, erreur, warning ou critique)"
f_dspl cmd "$dmesg_emerg" "dmesg -l emerg" "emergency, $nb_lignes premières lignes"
f_dspl cmd "$dmesg_alert" "dmesg -l alert" "alerte, $nb_lignes premières lignes"
f_dspl cmd "$dmesg_crit" "dmesg -l crit" "critique, $nb_lignes premières lignes"
f_dspl cmd "$dmesg_err" "dmesg -l err" "erreur, $nb_lignes premières lignes"
f_dspl cmd "$dmesg_warn" "dmesg -l warn" "warning, $nb_lignes premières lignes"
f_prnt l "**les $nb_lignes premières lignes commencent à la date la plus ancienne encore dans les logs kernel**"
f_prnt flush
f_dspl_alrt "$info_ucode" "info"
f_dspl_alrt "$alert_firmBug" "alert"
}
fi_efi(){ # 06/03/2018
local efiboot text
type -p efibootmgr &>/dev/null || return 0 # pas d'efibootmgr
efiboot=$( efibootmgr -v 2>/dev/null ) || return 0 # pas d'efi
efiboot=${efiboot// / } # amélioration légère
efiboot=${efiboot//\\/\\\\} # échappement des \
###
f_prnt tit2 "EFI boot"
f_dspl cmd "$efiboot" "efibootmgr -v" "config EFI boot"
}
# [$1=silent|xorgOnly], assigne $fe_gpu (liste des gpu), $fe_nb_gpu, fe_Xorg (peut être null)
# shellcheck disable=SC2086
# SC2086 Double quote to prevent globbing and word splitting
fi_gpu(){ # 06/03/2018
local toScrut confs ifile fileConfs cmd_confs cmt_confs info_config
local cards cmd_cards openGl pluriel text
local stck_glxinfo glx_dvc cmd_glx_dvc stck_glxinfoOpt stck_glxinfoDri glx_dvc_temp
local cmd_openGl stck_xrandr_query resolutions cmd_resolutions cmt_resolutions providers cmd_providers
local current_preferred cmd_current_preferred cmt_current_preferred
local modGpu cmd_modGpu cmt_modGpu
local alert_hybrid alert_3D alert_Wayland
x_gpu=1
# liste/description gpu et qte
figet_lspci "video" "name"
fe_gpu=${lspci[name]/VGA compatible controller: }
fe_gpu=${fe_gpu/VGA compatible controller: }
fe_gpu=${fe_gpu/Display controller: }
fe_gpu=${fe_gpu/3D controller: }
fe_nb_gpu=${lspci[nb_card]}
[ "$fe_nb_gpu" -eq 0 ] && return 0 # pas de gpu, rien à voir
# version Xorg Server
fe_Xorg=$( xdpyinfo -display "$DISPLAY" 2>/dev/null | grep -i 'x.*version' ) # X.Org version: 1.19.6
fe_Xorg=${fe_Xorg// version:} # X.Org 1.19.6
[ "$1" == "silent" ] && return 0
### ## xorgOnly (essai)
toScrut=(
"/etc/X11/xorg.conf"
"/etc/X11/xorg.conf.d/*.conf"
)
confs=$( f_grep_file "${toScrut[*]}" )
for ifile in "${toScrut[@]}"; do
[ -e $ifile ] && fileConfs+="$ifile " # ne pas quoter $ifile dans la condition pour permettre glob
done
cmd_confs="grep -Ersv '^#|^$' ${toScrut[*]}"
#~ [ "$fileConfs" ] || cmd_confs="Aucun fichier à afficher"
cmt_confs="configuration Xorg"
info_config="les configurations par défaut de Xorg se trouve dans **/usr/share/X11/xorg.conf.d/**, "
info_config+="non sorties ici."
if [ "$1" == "xorgOnly" ]; then
f_dspl cmd "$confs" "$cmd_confs" "$cmt_confs"
confs=$( f_grep_file "/usr/share/X11/xorg.conf.d/*" )
f_dspl cmd "$confs" "grep -Ersv '^#|^$' /usr/share/X11/xorg.conf.d/*" "config par défaut Xorg"
fi_journal_xorg "notitre"
return 0
fi
###
xrandr --auto 2>/dev/null
# lspci
# lspci -nnk | grep -EiA 3 'vga|display|3d'
# lspci -nnv | grep -iE -A10 'vga|display|3d'
# lspci -nnv -s $( lspci | grep -Ei 'vga|display|3d' | cut -d" " -f1 )
# lspci -nnv -s $( awk '/VGA |Display |3D / {print $1}' <<< "$( lspci )" )
figet_lspci "video" "raw"
cards=${lspci[card]}
cmd_cards="${lspci[prefix_gpu]}lspci -nnv -s \$( lspci | awk '/VGA |Display |3D / {print \$1}' )"
if grep -iq 'Unknown header type 7f' <<< "$cards" ; then
alert_hybrid="Une carte graphique semble désactivée actuellement, lspci n'est pas complet. \n"
fi
# openGl / glxinfo
if [[ "$wayland" && "$EUID" -eq 0 ]]; then # évite erreur $DISPLAY en root wayland
openGl="n/a:wayland root"
resolutions="n/a:wayland root"
providers="n/a:wayland root"
current_preferred="n/a:wayland root"
else
if type -p glxinfo &>/dev/null ; then
stck_glxinfo=$( glxinfo )
# test 3D actif
if grep -iq 'direct rendering: No' <<< "$stck_glxinfo" ; then
alert_3D="l'accélération 3D n'est pas active"
fi
# devices
glx_dvc=$( grep -i 'direct rendering:' <<< "$stck_glxinfo" )$'\n'
glx_dvc+=$( grep 'Device: ' <<< "$stck_glxinfo" | xargs )
cmd_glx_dvc="glxinfo | grep -E 'rendering|Device: '"
if [ "$fe_nb_gpu" -gt 1 ]; then # plusieurs cartes, optirun et prime
if type -p optirun &>/dev/null ; then
stck_glxinfoOpt=$( optirun glxinfo )
glx_dvc_temp=$( grep 'Device: ' <<< "$stck_glxinfoOpt" | xargs )
cmd_glx_dvc="optirun $cmd_glx_dvc"
else
stck_glxinfoDri=$( DRI_PRIME=1 glxinfo )
glx_dvc_temp=$( grep 'Device: ' <<< "$stck_glxinfoDri" | xargs )
cmd_glx_dvc="DRI_PRIME=1 $cmd_glx_dvc"
fi
[ "$glx_dvc_temp" != "$glx_dvc" ] && glx_dvc+="\n$glx_dvc_temp" # ajout si diff
fi
# openGL
fi_gpu_openGl # openGl pour une carte ou gpu de base
if [ "$fe_nb_gpu" -gt 1 ]; then # plusieurs cartes, optirun et prime
if type -p optirun &>/dev/null ; then
fi_gpu_openGl "opt" # ajout à $openGl existant, pas de redondance
cmd_openGl="optirun glxinfo | grep -E "
else # DRI
fi_gpu_openGl "dri" # redondance
cmd_openGl="DRI_PRIME=1 glxinfo | grep -E "
fi
else
cmd_openGl="glxinfo | grep -E "
fi
cmd_openGl+="'OpenGL vendor|OpenGL renderer|OpenGL version|shading language|OpenGL extensions'"
openGl=${openGl// string:/:} # suppression chaîne ' string'
openGl=${openGl% } # suppression espace final éventuel
fi
# xrandr: résolutionS & providers & preferred/current
if type -p xrandr &>/dev/null ; then
stck_xrandr_query=$( xrandr --query 2>/dev/null )
resolutions=$( grep -i 'screen' <<< "$stck_xrandr_query" )$'\n' # screen partie "carte graphique"
resolutions+=$( grep -A10 -iw 'connected' <<< "$stck_xrandr_query" ) # partie "output"
cmd_resolutions="xrandr --query | grep -A10 -B1 -i 'screen'"
cmt_resolutions="10 premières résolutions possibles"
providers=$( xrandr --listproviders 2>/dev/null ) # DRI: ok, sort 2 fournisseurs
cmd_providers="xrandr --listproviders"
current_preferred=$( xrandr --verbose 2>/dev/null | grep -EA2 'current|preferred' )
cmd_current_preferred="xrandr --verbose | grep -EA2 'current|preferred'"
cmt_current_preferred="résolution courante et préférée"
fi
fi
# modules utilisé
figet_lspci "video" "module"
modGpu="${lspci[module]}"
cmd_modGpu="lsmod | grep -Ew '${lspci[srch_mod]}'"
if [ "$( f__wcv -wv "$modGpu" "^[[:alnum:]]" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_modGpu="**Gpu:** $( f__wcv -wv "$modGpu" "^[[:alnum:]]" ) module$pluriel utilisé"$pluriel
# fonctions externes
(( x_screen )) || figet_screen
###
f_prnt tit2 "vidéo"
f_prnt 1 "$( sed -E 's/(.*)/**\1** /' <<< "$fe_gpu" )" # mise en gras
f_prnt
# nb écran & résolution(s) active(s)
f_prnt 1 "nombre d'écrans: **$fg_nb_screen**"
if [ "$( f__wcv "-wv" "$fg_resolution" "pixels" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt 1 "résolution$pluriel active$pluriel: **$fg_resolution**"
f_prnt
# lspci -nnv
f_dspl cmd "$cards" "$cmd_cards"
f_dspl_alrt "$alert_hybrid" "alert"
# wayland
f_dspl_alrt "$alert_Wayland" "info"
# openGl
f_dspl cmd "$glx_dvc" "$cmd_glx_dvc" "devices OpenGl"
f_dspl_alrt "$alert_3D" "info"
f_dspl cmd "$openGl" "$cmd_openGl" "OpenGl"
# liste providers, preferred & current
f_dspl cmd "$current_preferred" "$cmd_current_preferred" "$cmt_current_preferred"
f_dspl cmd "$providers" "$cmd_providers"
# résolutions possibles, pas d'affichage si mode (ssh) ou xrandr pas accessible
f_dspl cmd "$resolutions" "$cmd_resolutions" "$cmt_resolutions"
# modules vidéo
f_dspl cmd "$modGpu" "$cmd_modGpu" "$cmt_modGpu"
# Xorg config
f_dspl cmd "$confs" "$cmd_confs" "$cmt_confs"
f_dspl_alrt "$info_config" "info"
}
# $1="[opt|dri]", assigne $openGl, sous fonction de fi_gpu
fi_gpu_openGl(){ # 06/03/2018
local iogl dri_glxinfo=""
[[ "$1" == "opt" ]] && openGl+="\n---- \n"
toScrut=(
'OpenGL vendor'
'OpenGL renderer'
'OpenGL version'
'shading language'
'OpenGL extensions'
)
for iogl in "${toScrut[@]}" ; do
if [ "$1" == "dri" ]; then
dri_glxinfo+=$( grep "$iogl" <<< "$stck_glxinfoDri" )$'\n'
elif [ "$1" == "opt" ]; then
openGl+=$( grep "$iogl" <<< "$stck_glxinfoOpt" )$'\n'
else
openGl+=$( grep "$iogl" <<< "$stck_glxinfo" )$'\n'
fi
done
if [ "$1" == "dri" ]; then
dri_glxinfo=${dri_glxinfo::-1}
openGl=$( uniq <<< "$dri_glxinfo" 2>/dev/null ) || openGl="$dri_glxinfo"
fi
openGl=${openGl::-1}
}
fi_hw(){ # 14/12/2017
(( x_hw == 1 )) || figet_hw
###
f_prnt tit2 "hardware monitor"
f_dspl sans "$fg_hw" "sans"
f_prnt 1 "pas d'informations détectées" '[ -z "$fg_hw" ]'
f_prnt flush
}
fi_ip_pub(){ # 08/03/2018
local itest
for itest in -4 -6; do
if figet_ip_pub "$itest" ; then
echo "$BOLD$fg_ip_pub$STD"
else
echo "pas de connectivité ipv${itest#-}"
fi
done
}
# shellcheck disable=SC2181
# SC2181 Check exit code directly
fi_journal(){ # 06/03/2018
local file options_jctl jctl_boot jctl_alert_k jctl_crit_k jctl_err_k jctl_warn_k jctl_warn_nok jctl_last jctl_size
local info_ucode text nb_lignes=25
local alert_jctl_persist alert_firmBug
if ! type -p journalctl &>/dev/null ; then
fi_dmesg # pas systemd, appel dmesg
return 0
fi
file="/tmp/$script-journalctl"
if journalctl --help | grep -q -- '--no-hostname' ; then # fix obsolescence buntu 16.04
options_jctl="--no-hostname"
fi
if [ "$EUID" -ne 0 ] ; then
echo -e '\n'
f__info "raw" "les droits root sont demandés et requis pour afficher les journaux systèmes"
f__info "raw" "[su] nécessite la saisie du mot de passe root"
f__info "raw" "[sudo] nécessite le mot de passe utilisateur si celui peut obtenir les privilèges administrateur"
f__info "à défaut de saisie valide, les journaux n'apparaîtront pas dans le rapport final"
fi
f__sudo "LC_ALL=C journalctl $options_jctl --boot -1 &>$file-persistant ; \
LC_ALL=C journalctl --no-pager $options_jctl -b0 -k -p 1 > $file-alert ; \
LC_ALL=C journalctl --no-pager $options_jctl -b0 -k -p 2..2 > $file-crit ; \
LC_ALL=C journalctl --no-pager $options_jctl -b0 -p 3..3 > $file-err ; \
LC_ALL=C journalctl --no-pager $options_jctl -b0 -p 4..4 > $file-warn ; \
LC_ALL=C journalctl --no-pager $options_jctl -b0 -p 4 -n$nb_lignes > $file-last ; \
LC_ALL=C journalctl --disk-usage > $file-size ; \
LC_ALL=C journalctl --no-pager $options_jctl -o short-monotonic --boot 0 -k -p6 | grep -i 'microcode: .*updated early' > $file-ucode ; \
type -p dmesg &>/dev/null && dmesg -Hk --nopager | grep -i 'Firmware Bug' > $file-firmBug ; \
chown $fu_user: $file-*"
if [ "$?" != "0" ]; then
f__info "\n les commandes$GREEN journalctl$RED ont échoué $BLUE(droits root requis, échec authentification?)" \
"vous pouvez relancer le script complet$RED en root$BLUE pour voir les erreurs des journaux" \
"ou juste la partie journaux avec $GREEN$DIRNAME""getInfo -j"
text+="* les commandes \`journalctl\` ont échoué, relancer avec les droits root \n\n"
echo -e "$text" >> "$file_output"
return 0
fi
# début des logs, extraction à partir de file-last (toujours lignes) pour début des logs
jctl_boot=$( awk -F '--|,' 'FNR==1 {print $2}' $file-last )
jctl_boot=$( date -d "${jctl_boot##*begin at }" ) # passage en date locale
# test persistance
if grep -iq 'no persistent journal' "$file-persistant"; then
alert_jctl_persist="les journaux ne sont pas persistants, revoir les logs du précédent boot "
alert_jctl_persist+="n'est donc pas possible pour investigation avec: \n"
alert_jctl_persist+="$spc5 **journalctl $options_jctl --boot -1**"
fi
# journaux kernel
jctl_alert_k=$( sed '/kernel:/!d' $file-alert | sed -n 1,"$nb_lignes"p ) # emergency & alert
jctl_crit_k=$( sed '/kernel:/!d' $file-crit | sed -n 1,"$nb_lignes"p )
jctl_err_k=$( sed '/kernel:/!d' $file-err | sed -n 1,"$nb_lignes"p ) # uniquement lignes avec kernel, élimine no entries et logs begin
jctl_warn_k=$( sed '/kernel:/!d' $file-warn | sed -n 1,"$nb_lignes"p )
# taille des journaux
jctl_size=$( grep -Eo '[0-9]*\.[0-9]*[[:alpha:]]{1,2}' $file-size | sed 's/M/ Mo/' )
# signalement fichier vides ou suppression origine kernel (gain de place)
[ "$jctl_alert_k" ] && jctl_alert_k=${jctl_alert_k//kernel:/:} || jctl_alert_k=" ‣ vide"
[ "$jctl_crit_k" ] && jctl_crit_k=${jctl_crit_k//kernel:/:} || jctl_crit_k=" ‣ vide"
[ "$jctl_err_k" ] && jctl_err_k=${jctl_err_k//kernel:/:} || jctl_err_k=" ‣ vide"
[ "$jctl_warn_k" ] && jctl_warn_k=${jctl_warn_k//kernel:/:} || jctl_warn_k=" ‣ vide"
# journaux hors kernel
jctl_alert_nok=$( sed '/-- Logs begin/d;/kernel:/d; s/-- No entries --/ ‣ vide/' $file-alert | \
sed -n 1,"$nb_lignes"p )
jctl_crit_nok=$( sed '/-- Logs begin/d;/kernel:/d; s/-- No entries --/ ‣ vide/' $file-crit | \
sed -n 1,"$nb_lignes"p )
jctl_err_nok=$( sed '/-- Logs begin/d;/kernel:/d; s/-- No entries --/ ‣ vide/' $file-err | \
sed -n 1,"$nb_lignes"p )
jctl_warn_nok=$( sed '/-- Logs begin/d;/kernel:/d; s/-- No entries --/ ‣ vide/;s/<warn>//
' $file-warn | sed -n 1,"$nb_lignes"p )
# dernières lignes, toute provenance
jctl_last=$( sed '/-- Logs begin/d; s/-- No entries --/ ‣ vide/;s/<warn>//' $file-last )
# messages microcode
info_ucode=$( cat $file-ucode )
[ "$info_ucode" ] && info_ucode="microcode processeur mis à jour au boot"
alert_firmBug=$( grep -i 'Firmware Bug' <<< "$jctl_err_k" )$'\n'
alert_firmBug=${alert_firmBug%%[[:space:]]}
alert_firmBug+=$( cat $file-firmBug 2>/dev/null )
alert_firmBug=${alert_firmBug%%[[:space:]]}
# suppression fichier de transfert
rm "$file-"*
###
f_prnt tit2 "journalctl kernel (emergency, alert, erreur, warning ou critique)"
f_prnt 1 "**journaux persistants**" '[ -z "$alert_jctl_persist" ]'
f_prnt 1 "Début des log: **$jctl_boot**"
f_prnt
f_dspl_alrt "$alert_jctl_persist" "info"
# journaux kernel
f_dspl cmd "$jctl_alert_k" "journalctl $options_jctl -b0 -k -p1" \
"**kernel emergency 0 & alerte 1**, $nb_lignes premières lignes"
f_dspl cmd "$jctl_crit_k" "journalctl $options_jctl -b 0 -k -p 2..2" \
"**kernel critique**, $nb_lignes premières lignes"
f_dspl cmd "$jctl_err_k" "journalctl $options_jctl -b0 -k -p 3..3" \
"**kernel erreur**, $nb_lignes premières lignes)"
f_dspl cmd "$jctl_warn_k" "journalctl $options_jctl -b0 -k -p 4..4" \
"**kernel warning**, $nb_lignes premières lignes"
# journaux hors kernel
f_prnt tit2 "journalctl hors kernel (emergency, alert, erreur, warning ou critique)"
f_prnt 1 "Début des log: **$jctl_boot**"
f_prnt
f_dspl cmd "$jctl_alert_nok" "journalctl $options_jctl -b0 -p 1 | grep -v kernel" \
"**hors kernel, emergency 0 & alerte 1**, $nb_lignes premières lignes"
f_dspl cmd "$jctl_crit_nok" "journalctl $options_jctl -b0 -p 2..2 | grep -v kernel" \
"**hors kernel, critique**, $nb_lignes premières lignes"
f_dspl cmd "$jctl_err_nok" "journalctl $options_jctl -b0 -p 3..3 | grep -v kernel" \
"**hors kernel, erreur**, $nb_lignes premières lignes"
f_dspl cmd "$jctl_warn_nok" "journalctl $options_jctl -b0 -p 4..4 | grep -v kernel" \
"**hors kernel, warning**, $nb_lignes premières lignes"
#informations
f_prnt 1 "les $nb_lignes premières lignes commencent à la date du dernier boot"
f_prnt
f_dspl cmd "$jctl_size" "journalctl --disk-usage " "taille des journaux"
# dernières lignes
f_dspl cmd "$jctl_last" "journalctl $options_jctl -b0 -p 4 -n25" \
"**toutes provenance, emergency-warning**, $nb_lignes lignes les plus **récentes**"
f_dspl_alrt "$alert_firmBug" "alert"
f_dspl_alrt "$info_ucode" "info"
}
# [$1=notitre]
fi_journal_xorg(){ # 08/03/2018
local toScrut xfile xfileTest="" logXorg cmd_logXorg="" cmt_logXorg extract dateFile text nb_lignes=50
local info_logs alert_cyrilic
[[ "$ENV_SSH" || "$ENV_DISPLAY" ]] && return 0
(( x_dm == 1 )) || figet_dm
toScrut=(
/var/log/Xorg.0.log
/home/$fu_user/.local/share/xorg/Xorg.0.log
)
[[ "${fg_dm,,}" =~ gdm ]] && toScrut=( ${toScrut[@]} "/var/lib/gdm3/.local/share/xorg/Xorg.0.log" )
for xfile in "${toScrut[@]}"; do
[ -e "$xfile" ] && xfileTest+="y"
done
[ ${#xfileTest} -eq 0 ] && return 0 # aucun fichier à tester (wayland?), retour
# coeur fonction
for xfile in "${toScrut[@]}"; do
if [ -e "$xfile" ]; then
dateFile=$( date -r "$xfile" '+%d/%m/%Y %H:%M %z' )
extract=$( grep -Es '\(WW\)|\(EE\)|\(\?\?\)' "$xfile" | sed '/(WW) warning, (EE) error,/d' )
extract=$( sed -n 1,"$nb_lignes"p <<< "$extract" )
if [ "$extract" ]; then
logXorg+=" $xfile, date de modification: $dateFile \n\n"
logXorg+=" (WW) **warning**, (EE) **erreur**, (??) inconnu, $nb_lignes premières lignes \n"
logXorg+=$( grep -E '\(EE\)' <<< "$extract" )$'\n'
logXorg+=$( grep -E '\(WW\)' <<< "$extract" )$'\n'
logXorg+=$( grep -E '\(\?\?\)' <<< "$extract" )" "$'\n\n'
cmd_logXorg+="$xfile "
else
logXorg+=" $xfile : <vide> "$'\n\n'
fi
else
logXorg+=" $xfile : <inexistant> "$'\n\n'
fi
done
logXorg=${logXorg::-2}
[ "$cmd_logXorg" ] && cmd_logXorg=${cmd_logXorg% } || cmd_logXorg="<emplacement>"
cmd_logXorg="grep -Es '\(WW\)|\(EE\)|\(\?\?\)' $cmd_logXorg"
cmt_logXorg="Xorg.log"
info_logs="voir les options appliquées par défaut: **cat $cmd_logXorg | grep '(\\\*\\\*)**' "
alert_cyrilic=$( grep '/usr/share/fonts/X11/cyrillic" does not exist' <<< "$logXorg" )
if [ "$alert_cyrilic" ]; then
alert_cyrilic=${alert_cyrilic#*) }
alert_cyrilic=${alert_cyrilic%\.}
alert_cyrilic+=": \npour éviter ce message, en root : \`mkdir -p /usr/share/fonts/X11/cyrillic\`"
fi
###
f_prnt tit2 "journaux Xorg" "[ \"$1\" != \"notitre\" ]"
f_dspl cmd "$logXorg" "$cmd_logXorg" "$cmt_logXorg"
f_dspl_alrt "$info_logs" "info"
f_dspl_alrt "$alert_cyrilic" "alert"
}
fi_locale(){ # 06/03/2018
local localeConf localeCtl locale timezone timedatectl xKeyboardMap keyboard text
local alert_rtc alert_ntp
# locale
localeConf=$( f_grep_file "/etc/default/locale* /etc/locale.conf" )
localeCtl=$( localectl --no-pager status 2>/dev/null )
locale=$( locale )
# timezone
timezone=$( f_grep_file "/etc/timezone*" )
if type -p timedatectl &>/dev/null ; then
timedatectl=$( LC_ALL=C timedatectl status --no-pager )
if grep -iq 'Network time on: no' <<< "$timedatectl"; then
alert_ntp="Network time on: no \n"
alert_ntp+="Le système ne synchronise pas l'heure sur un serveur NTP. Si ce n'est pas voulu: \n"
alert_ntp+="activer le service: timedatectl set-ntp true \n"
alert_ntp+="et/ou installer le démon Ntp: apt install ntp"
fi
if grep -iq 'RTC in local TZ: yes' <<< "$timedatectl"; then
alert_rtc="RTC in local TZ: yes \n"
alert_rtc+="Lhorloge système doit être en UTC pour que les applications de date et "
alert_rtc+="heure fonctionnent correctement avec le fuseau horaire configuré sur le système. \n"
alert_rtc+="Les modifications dheure dété/hiver peuvent être incohérentes quand lhorloge "
alert_rtc+="matérielle est en heure locale."
fi
fi
# keyboard layout
keyboard=$( f_grep_file "/etc/default/keyboard*" )
if [[ "$wayland" && "$EUID" -eq 0 ]]; then # na root wayland
xKeyboardMap="n/a en root sous wayland"
elif [[ "$ENV_SSH" && -z "$DISPLAY" ]]; then # na ssh
xKeyboardMap="n/a avec ssh"
elif [[ "$ENV_SSH" && "$EUID" -eq 0 && ${DISPLAY%:*} ]]; then # na ssh X root
xKeyboardMap="n/a avec ssh X sous root"
elif [[ -z "$DISPLAY" ]]; then # na noX
xKeyboardMap="n/a sans serveur X"
else
xKeyboardMap=$( setxkbmap -query 2>/dev/null )
fi
###
f_prnt tit2 "localisation"
# locale
f_dspl cmd "$localeConf" "grep -Esv '#|^$' /etc/default/locale* /etc/locale.conf"
f_dspl cmd "$localeCtl" "localectl status"
f_dspl cmd "$locale" "locale"
# timezone
f_dspl cmd "$timezone" "grep -EHsv '#|^$' /etc/timezone*"
f_dspl cmd "$timedatectl" "timedatectl status"
f_dspl_alrt "$alert_ntp" "info"
f_dspl_alrt "$alert_rtc" "alert"
# keyboard layout
f_dspl cmd "$keyboard" "grep -EHv '#|^$' /etc/default/keyboard*"
f_dspl cmd "$xKeyboardMap" "setxkbmap -query"
}
fi_mem(){ # 21/02/2018
local memoire swappiness swapType text
figet_mem "mem" #options possibles mem swap total notitle nocoltitle
memoire="$fg_mem \n"
figet_mem "swap" "notitle"
memoire+="$fg_mem"
swappiness=$( cat /proc/sys/vm/swappiness 2>/dev/null )
swapType=$( awk 'FNR != 1 { print $2,":", $1 }' /proc/swaps )
###
f_prnt tit2 "mémoire"
f_dspl cmd "$memoire" "free -h"
f_dspl cmd "$swapType" "awk 'FNR != 1 { print \$2,\":\", \$1 }' /proc/swaps" "type de swap"
f_dspl cmd "$swappiness" "cat /proc/sys/vm/swappiness" "Seuil bas de RAM libre où le swap est utilisé"
}
# [$1=silent], assigne fe_nb_reseau, fe_cards_reseau
fi_net(){ # 07/03/2018 ( matériel )
local cards cmd_cards modEth cmd_modEth cmt_modEth modWln cmd_modWln cmt_modWln pluriel text
local alert_wlx
x_net=1
# devices
figet_lspci "net" "name" # noms des cartes réseau détectées, mix ethernet/wifi
fe_cards_reseau=${lspci[name]/Network controller: /Wireless: }
fe_cards_reseau=${fe_cards_reseau/Wireless Network/Wireless}
fe_cards_reseau=${fe_cards_reseau/Ethernet controller: /Ethernet: }
fe_nb_reseau=${lspci[nb_card]} # nombre de cartes réseau détectées, mix ethernet/wifi
[ "$1" == "silent" ] && return
[ "$fe_nb_reseau" -eq 0 ] && return 0 # pas de cartes réseau, rien à voir (en attendant usb ou autre)
###
# lspci
# lspci -nnk | grep -EiA 3 'network|ethernet'
# lspci -nnv -s $( lspci | grep -Ei 'network' | cut -d" " -f1 )
# lspci -nnv -s $( lspci | grep -Ei 'ethernet' | cut -d" " -f1 )
figet_lspci "net" "raw"
cards=${lspci[card]}
cmd_cards="lspci -nnv | grep -Ei -A10 'network|ethernet'"
#modules ethernet
figet_lspci "ethernet" "module" # obtention module utilisé
modEth="${lspci[module]}"
cmd_modEth="lsmod | grep -Ew '${lspci[srch_mod]}'"
if [ "$( f__wcv -wv "$modEth" "^[[:alnum:]]" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_modEth="**Ethernet:** $( f__wcv -wv "$modEth" "^[[:alnum:]]" ) module$pluriel utilisé"$pluriel
# modules wifi
figet_lspci "wireless" "module" # obtention module utilisé
modWln="${lspci[module]}"
cmd_modWln="lsmod | grep -Ew '${lspci[srch_mod]}'"
if [ "$( f__wcv -wv "$modWln" "^[[:alnum:]]" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_modWln="**Wifi:** $( f__wcv -wv "$modWln" "^[[:alnum:]]" ) module$pluriel utilisé"$pluriel
figet_ip
if grep -iq 'wlx' <<< "$fg_ifn"; then
alert_wlx="Une interface wifi est en erreur: $( grep 'wlx' <<< "${fg_ifn// /$'\n'}" ) \n"
alert_wlx+="l'interface n'est pas reconnue et est donc mal nommée, "
alert_wlx+="éventuellement, changer le renommage: \n"
alert_wlx+="https://kyodev.frama.io/kyopages/trucs/interfaces-nommage-classique/"
fi
###
f_prnt tit2 "réseau"
f_prnt 1 "$( sed -E 's/(.*)/**\1** /' <<< "$fe_cards_reseau" )" # mise en gras
f_prnt
# lspci -nnv
f_dspl cmd "$cards" "$cmd_cards"
# modules réseau
f_dspl cmd "$modEth" "$cmd_modEth" "$cmt_modEth"
f_dspl cmd "$modWln" "$cmd_modWln" "$cmt_modWln"
f_dspl_alrt "$alert_wlx" "alert"
}
fi_nm(){ # 06/03/2018
local nm_etat cmd_nm_etat cmt_nm_etat nm_conf cmd_nm_conf cmt_nm_conf nm_wifis cmd_nm_wifis cmt_nm_wifis text
type -p nmcli &>/dev/null || return 0
nm_etat=$( f_grep_file "/var/lib/NetworkManager/NetworkManager.state" "notitre" )
cmd_nm_etat="grep -Ev '#|^$' /var/lib/NetworkManager/NetworkManager.state"
cmt_nm_etat="état de NetworkManager"
nm_conf=$( f_grep_file "/etc/NetworkManager/NetworkManager.conf /etc/NetworkManager/conf.d/*.conf" )
cmd_nm_conf="grep -Ev '#|^$' /etc/NetworkManager/NetworkManager.conf /etc/NetworkManager/conf.d/*.conf"
cmt_nm_conf="configuration de NetworkManager"
nm_wifis=$( LC_ALL=C nmcli -f SSID,BSSID,MODE,CHAN,FREQ,RATE,SIGNAL,BARS,SECURITY device wifi list | head -n15 )
cmd_nm_wifis="nmcli -f SSID,BSSID,MODE,CHAN,FREQ,RATE,SIGNAL,BARS,SECURITY device wifi list"
cmt_nm_wifis="wifis à proximité"
[ "$(f__wcv "-l" "$nm_wifis")" -eq 1 ] && unset nm_wifis # si jamais sortie entête quand pas de wifi, possible?
###
f_prnt tit2 "NetworkManager"
f_dspl cmd "$nm_etat" "$cmd_nm_etat" "$cmt_nm_etat"
f_dspl cmd "$nm_conf" "$cmd_nm_conf" "$cmt_nm_conf"
f_dspl cmd "$nm_wifis" "$cmd_nm_wifis" "$cmt_nm_wifis"
}
fi_packagers(){ # 23/11/2017
local alert_pkg_todo="ce gestionnaire de paquets n'est pas maîtrisé par manque d'expertise \n"
alert_pkg_todo+="vous êtes donc bienvenus à contribuer dans ce domaine: \n"
alert_pkg_todo+="https://framagit.org/kyodev/kyopages/blob/master/scripts/CONTRIB.md#getinfo"
if type -p dpkg &>/dev/null ; then # debian, buntu apt/dpkg
unset alert_pkg_todo # modèle, alert_pkg_todo pas implanté dans fi_pkg_apt
fi_pkg_apt "apt:apt/dpkg"
elif type -p dnf &>/dev/null || type -p yum &>/dev/null ; then # Fedora, RedHat (rpm)
fi_pkg_x "dnf:dnf/rpm"
elif type -p pacman &>/dev/null ; then # ArchLinux, Chakra Linux, Manjaro, KaOS, Parbola, Antergos, Apricity
fi_pkg_x "pacman:Pacman"
elif type -p pacman-g2 &>/dev/null ; then # Frugalware
fi_pkg_x "pacman-g2:Pacman-g2"
elif type -p emerge &>/dev/null ; then # Gentoo
fi_pkg_x "portage:portage/emerge"
elif type -p installpkg &>/dev/null || type -p slackpkg &>/dev/null ; then # Slackware, slackpkg gestion automatique paquets
fi_pkg_x "slackware:Slackware"
elif type -p zypper &>/dev/null ; then # Suse, openSuse
fi_pkg_x "zypper:zypper/rpm"
elif type -p alps &>/dev/null ; then # AryaLinux
fi_pkg_x "x:alps"
elif type -p eopkg &>/dev/null ; then # Solus Linux
fi_pkg_x "x:eopkg"
elif type -p guix &>/dev/null ; then # GNU Guix
fi_pkg_x "x:Guix"
elif type -p lvu &>/dev/null ; then # Lunar Linux
fi_pkg_x "x:lvu"
elif type -p nix-env &>/dev/null ; then # Nix: NixOs
fi_pkg_x "x:Nix"
elif type -p opkg &>/dev/null ; then # opkg fork ipkg, ipkg (abandonné) sauf sur Syno?
fi_pkg_x "x:opkg"
elif type -p sorcery &>/dev/null ; then # SourceMage
fi_pkg_x "x:Sorcery"
elif type -p tazpkg &>/dev/null ; then # SliTaz
fi_pkg_x "x:tazpkg"
elif type -p tce-status &>/dev/null ; then # TinyCoreLinux
fi_pkg_x "x:TinyCoreExtensions"
elif type -p xbps-query &>/dev/null ; then # VoidLinux
fi_pkg_x "x:VoidLinux"
else
fi_pkg_x "x:Inconnue"
fi
}
# shellcheck disable=SC2034
# SC2034 foo appears unused. Verify it or export it.
fi_pkg_apt(){ # 15/03/2018
local dateMaj nb_packages ifile info_update text pluriel
local sources cmt_sources cmd_sources result
local apt_v apt_version apt_prefs cmt_apt_prefs cmd_apt_prefs alert_non_pref
local stck_upgd qte_upgradable
local upgrade cmt_upgrade cmd_upgrade
local notUpgraded cmt_notUpgraded
local toRemove qte_toRemove cmt_toRemove cmd_toRemove
local autoclean qte_autoclean cmt_autoclean cmd_autoclean
local clean qte_clean cmt_clean cmd_clean size_cleanH
local non_ii qte_non_ii cmt_non_ii cmd_non_ii etat ligne stck_etat
local deborphan qte_deborphan cmt_deborphan cmd_deborphan
local holded qte_holded cmt_holded cmd_holded
local pinned tempo qte_pinned cmd_pinned cmt_pinned
local kernel cmd_kernel cmt_kernel
local alert_https alert_httpsPossible alert_non_list alert_httpredir alert_upgrade alert_full_upgrade
local alert_apt alert_remove alert_autoclean alert_clean alert_non_ii alert_deborphan
# sources
sources=$( f_grep_file "/etc/apt/sources.list /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources" "sources date" )
cmt_sources="dépôts"
cmd_sources="grep -Ersv '^#|^$' /etc/apt/sources.list /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources"
# sources ignorées
result=$( f_policy "sources" )
if [ "$result" ] ; then
alert_non_list="ignoré: \n$result"
fi
unset result
# preferences
apt_prefs=$( f_grep_file "/etc/apt/preferences /etc/apt/preferences.d/*" "lignevide date" )
cmd_apt_prefs="grep -Erv '^#|^$' /etc/apt/preferences /etc/apt/preferences.d/"
cmt_apt_prefs="préférences apt"
# preferences ignorées
result=$( f_policy "preferences" )
if [ "$result" ] ; then
alert_non_pref="ignoré: \n$result"
fi
# essai confOnly
if [ "$1" == "confOnly" ]; then
local apt_unUpgrd cmd_unUpgrd cmd_apt_history essai
# apt_unUpgrd=$( f_grep_file "/etc/apt/apt.conf.d/!(*.save)" "comment//" )
apt_unUpgrd=$( f_grep_file "/etc/apt/apt.conf.d/50unattended-upgrades" "comment//" )
cmd_unUpgrd="grep -Erv '^//|^$' /etc/apt/apt.conf.d/50unattended-upgrades"
if [ "$apt_unUpgrd" ]; then
info_unUpgrd="les logs spécifiques unattended-upgrades: "
info_unUpgrd+="**ls -l /var/log/unattended-upgrades/*.log**"
fi
f_dspl cmd "$sources" "$cmd_sources" "$cmt_sources"
f_dspl cmd "$apt_prefs" "$cmd_apt_prefs" "$cmt_apt_prefs"
f_dspl cmd "$apt_unUpgrd" "$cmd_unUpgrd" ".conf unattended-upgrades"
f_dspl_alrt "$info_unUpgrd" "info"
#f_dspl cmd "$( tail -n20 /var/log/syslog )" "$( tail -n20 /var/log/syslog )" "20 derniers logs"
#f_dspl cmd "$( tail -n25 /var/log/apt/history.log )" "tail -n25 /var/log/apt/history.log" "25 derniers historiques apt"
#f_dspl sans "$( f_grep_file "/var/log/unattended-upgrades/*.log" )"
IFS=$'\n'
# essai=( grep -B1 -A2 'unattended-upgrade' /var/log/apt/history.log )
# for i in "${!essai[@]}"; do
# for i in /var/log/unattended-upgrades/* ; do
# done
# f_dspl cmd $(echo "${essai[*]}") "$cmt_apt_history"
#echo ${#essai[*]}
#echo ${essai[3]}
IFS="$IFS_INI"
return 0
fi
# avertissement
info_update="apt update n'a pas été lancé, vérifier que la date de mise à jour ne soit pas trop ancienne."
# divers
dateMaj=$( date -r /var/lib/apt/lists '+%d/%m/%Y %H:%M %z' 2>/dev/null ) || dateMaj="n/a"
nb_packages=$( dpkg -l | grep -c '^ii' ) # alternatif: ls -1 /var/lib/dpkg/info/*.list | grep -c '\.list'
# https
apt_version=$( apt --version ) # apt 1.4.8 (i386)
apt_version=${apt_version#apt } # 1.4.8 (i386)
apt_version=${apt_version% (*} # 1.4.8
apt_v=${apt_version%.*} # 1.4
alert_https=$( awk '{if ( $1 > 1.5 ) {print "https inutile"}}' <<< "$apt_v" )
if f__requis_deb "apt-transport-https" && [ "$alert_https" ]; then
alert_https="le paquet <apt-transport-https> est inutile maintenant avec la version $apt_v d'apt (depuis 1.6)"
else
unset alert_https
fi
alert_httpsPossible=$( awk '{if ( $1 > 1.5 ) {print "https possible"}}' <<< "$apt_v" )
if [ "$alert_httpsPossible" ]; then
alert_httpsPossible="votre version d'apt ($apt_v) permet d'utiliser simplement les sources avec "
alert_httpsPossible+="le protocole https et les dépôts deb.debian.org"
fi
# httpredir
if grep -iq 'httpredir' <<< "$sources" ; then
alert_httpredir="ces urls sont obsolètes, préférer http://deb.debian.org/ ou un miroir local: \n\n"
alert_httpredir+=$( grep 'httpredir' <<< "$sources" )
fi
echo -n "◇"
# extraction qte ugrade, full-upgrade
stck_upgd=$( LC_ALL=C apt-get upgrade --simulate 2>/dev/null )
# $1 upgraded, $6 to remove, $10 not upgraded # => qte_upgradable [0]=upgraded, [1]=notUpgraded
qte_upgradable=( $( awk '/ newly installed/{print $1" "$10}' <<< "$stck_upgd" ) ) # tableau
[ "${qte_upgradable[0]}" ] || qte_upgradable=("-1" "-1") # si erreur
# upgrade
if [ $(( qte_upgradable[0] )) -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_upgrade="${qte_upgradable[0]} paquet$pluriel à mettre à jour"
[ "${qte_upgradable[0]}" -eq 0 ] && cmt_upgrade=${cmt_upgrade/0 /aucun }
# /!\ apt list --upgradable ne tient pas compte des paquets figés dans preferences (et holded?) et
# donc résultat > à apt-get upgrade --simulate | grep -c '^Inst '
cmd_upgrade="apt-get upgrade --simulate"
if [ "${qte_upgradable[0]}" -gt 0 ]; then
upgrade=$( grep '^Inst' <<< "$stck_upgd" | sort | awk '{
paquet=$2; paquet=substr(paquet,1,30)
sub(/\[/,"",$3); sub(/\]/,"",$3); $3=substr($3,1,20); ver_ini=$3
sub(/\(/,"",$4); $4=substr($4,1,20); ver_final=$4
$1=$2=$3=$4=""
source=$0; sub(/\/.*/,"",source); gsub(/\[.*\]/,"",source); gsub(/\)/,"",source)
gsub(/^ */,"",source);gsub(/,/,", ",source)
printf "%-30s %-20s ⇉ %-20s %s \n",paquet,ver_ini,ver_final,source
}')
alert_upgrade="ces paquets peuvent être mis à jour avec: **apt upgrade**"
elif [ "${qte_upgradable[0]}" -lt 0 ]; then
upgrade="• erreur apt, les paquets à mettre à jour ne peuvent être déterminés"
alert_apt="Erreur apt, vérifier avec **apt update ; apt upgrade** et analyser les messages"
fi
# full-upgrade
if [ "${qte_upgradable[1]}" -gt 0 ]; then
notUpgraded=${stck_upgd%The following packages will be upgraded*} # suppression fin
notUpgraded=${notUpgraded#*The following packages have been kept back:} # suppression début
notUpgraded=$( sed '/newly/d' <<< "$notUpgraded" | sort | tr '\n' ' ' )
notUpgraded=${notUpgraded// / } # suppression espace double
if [ $(( qte_upgradable[1] )) -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_notUpgraded="${qte_upgradable[1]} paquet$pluriel nécessitant une mise à jour profonde (dist-upgrade)"
alert_full_upgrade="ces paquets peuvent être mis à jour avec avec: **apt dist-upgrade**"
fi
echo -n "◇"
# autoremove
toRemove=$( LC_ALL=C apt-get autoremove --simulate | grep -E 'Remv | newly installed' )
toRemove=$( sort <<< "$toRemove" )
qte_toRemove=$( awk '/ newly installed/{ printf $6 }' <<< "$toRemove" )
toRemove=$( sed '/newly/d' <<< "$toRemove" ) # suppression ligne état
if [ $(( qte_toRemove )) -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_toRemove="$qte_toRemove paquet$pluriel inutile"$pluriel
[ "$qte_toRemove" -eq 0 ] && cmt_toRemove=${cmt_toRemove/0 /aucun }
cmd_toRemove="apt autoremove"
if [ "$qte_toRemove" -gt 0 ]; then
toRemove=$( sed -E '/^Remv/!d; s/\[.*\]//g; s/Remv //' <<< "$toRemove" | tr '\n' ' ' )
toRemove=${toRemove// / }
alert_remove="les paquets peuvent être supprimés avec: **apt autoremove --purge** \n"
alert_remove+="vérifier que la liste ne contient pas des applications devenues importantes \n"
alert_remove+="au besoin, les marquer comme installées manuellement avec apt-mark manual <paquet> \n"
alert_remove+="ou les installer manuellement avec apt install <paquet>"
fi
# autoclean
echo -n "◇"
autoclean=$( LC_ALL=C apt-get autoclean --simulate 2>/dev/null | awk '/^Del/{print $2}' | sort | tr '\n' ' ' )
qte_autoclean=$( f__wcv -w "$autoclean" )
if [ "$qte_autoclean" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_autoclean="$qte_autoclean archive$pluriel périmée"$pluriel
[ "$qte_autoclean" -eq 0 ] && cmt_autoclean=${cmt_autoclean/0 /aucune }
cmd_autoclean="apt autoclean"
if [ "$qte_autoclean" -gt 0 ]; then
alert_autoclean="ces archives de paquets, sans utilité directe dans le système, "
alert_autoclean+="peuvent être supprimées avec: **apt autoclean**"
fi
# clean
clean=$( LC_ALL=C du -chS /var/cache/apt/archives/ 2>/dev/null )
clean=$( f__unit_french "$clean" )
size_cleanH=$( du -chS /var/cache/apt/archives/ 2>/dev/null | grep -i 'total' ) # affichage en human
size_cleanH=${size_cleanH%[[:blank:]]total}
size_cleanH=$( f__unit_french "$size_cleanH" )
qte_clean=$( f__dir -c /var/cache/apt/archives "lock|partial" )
if [ "$qte_clean" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_clean="taille du cache des paquets"
cmd_clean="du -chS /var/cache/apt/archives/"
if [ "$qte_clean" -gt 0 ]; then # alerte si > à 100 ko (cache pas vide)
alert_clean="$qte_clean archive$pluriel dans le cache de téléchargement des paquets \n"
alert_clean+="$size_cleanH pourraient être libérés en effaçant ce cache: **apt clean**"
else # cache vide (72ko à 120ko)
clean="• cache vide"
fi
# paquet non ^ii
non_ii=$( LC_ALL=C dpkg -l | awk 'FNR>5 && ! /^i/ {
printf "%-3s %-25s %-12s",$1,$2,$3; $1=$2=$3=$4=""; printf "%s \n",$0 }' )
qte_non_ii=$( f__wcv -l "$non_ii" )
if [ "$qte_non_ii" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_non_ii="$qte_non_ii paquet$pluriel dans un état non standard (^ii)"
[ "$qte_non_ii" -eq 0 ] && cmt_non_ii=${cmt_non_ii/0 /aucun }
cmd_non_ii="dpkg -l | grep -v '^ii'" # dpkg -l | awk '! /^ii/ {print $0}'
if [ "$qte_non_ii" -gt 0 ]; then
# extraction différents états constatés
while read -r etat ligne ; do
stck_etat+="$etat"$'\n'
done <<< "$non_ii"
stck_etat=$( sort -u <<< "$stck_etat" ) # tri et dédoublonnage
non_ii+="\n\n ‣ État souhaité / État du paquet / Drapeaux d'erreur\n"
for ligne in $stck_etat; do
[[ ${ligne,,} =~ ^h ]] && non_ii+=" h: hold (à garder) "
[[ ${ligne,,} =~ ^i ]] && non_ii+=" i: install (à installer) "
[[ ${ligne,,} =~ ^p ]] && non_ii+=" p: purge (à purger) "
[[ ${ligne,,} =~ ^r ]] && non_ii+=" r: remove (à supprimer) "
[[ ${ligne,,} =~ ^u ]] && non_ii+=" u: unknown (inconnu) "
[[ ${ligne,,} =~ ^.c ]] && non_ii+=" c: config-files (fichiers de configuration) "
[[ ${ligne,,} =~ ^.f ]] && non_ii+=" f: halF-configured-configured (semi-configuré) "
[[ ${ligne,,} =~ ^.h ]] && non_ii+=" h: Half-installed (semi-installé) "
[[ ${ligne,,} =~ ^.i ]] && non_ii+=" i: installed (installé) "
[[ ${ligne,,} =~ ^.n ]] && non_ii+=" n: not-installed (non installé) "
[[ ${ligne,,} =~ ^.t ]] && non_ii+=" t: triggers-pending (actions différées en cours) "
[[ ${ligne,,} =~ ^.u ]] && non_ii+=" u: unpacked (décompressé seulement) "
[[ ${ligne,,} =~ ^.w ]] && non_ii+=" w: triggers-awaiting (attente actions différées) "
[[ ${ligne,,} =~ ^..r ]] && non_ii+=" r: (réinstallation requise) " || non_ii+=" / . "
non_ii+=$'\n'
done
non_ii=${non_ii::-1} # suppression $'\n'
if grep -q '^rc' <<< "$stck_etat"; then
alert_non_ii="les paquets dans un état 'rc' (fichiers de configuration orphelins) "
alert_non_ii+="peuvent être purgés avec: \n"
alert_non_ii+="**dpkg --purge \$(dpkg -l | awk '/^rc/{print \$2}')**"
fi
fi
# deborphan éventuel
if type -p deborphan &>/dev/null ; then
deborphan=$( deborphan -P )
cmd_deborphan="deborphan -P"
qte_deborphan=$( f__wcv "-l" "$deborphan" )
if [ "$qte_deborphan" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_deborphan="$qte_deborphan bibliothèque$pluriel orpheline"$pluriel
[ "$qte_deborphan" -eq 0 ] && cmt_deborphan=${cmt_deborphan/0 /aucune }
if [ "$qte_deborphan" -gt 0 ]; then
alert_deborphan="bibliothèque$pluriel orpheline$pluriel, suppression possible: \n"
alert_deborphan+="**apt purge \$(deborphan)** \n"
alert_deborphan+="recherche légère, mais vérifier avant de valider la suppression \n"
alert_deborphan+="Relancer la commande jusqu'à vidage complet, les bibliothèques pouvant "
alert_deborphan+="s'installer en cascade"
fi
fi
# paquets figés (hold)
holded=$( apt-mark showhold | sort | tr '\n' ' ')
qte_holded=$( f__wcv "-w" "$holded" )
if [ "$qte_holded" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_holded="$qte_holded paquet$pluriel figé"$pluriel
[ "$qte_holded" -eq 0 ] && cmt_holded=${cmt_holded/0 /aucun }
cmd_holded="apt-mark showhold"
# paquets épinglés (pinning)
pinned=$( apt-cache policy | grep '\->' )
while read -r ; do
f__trim "REPLY"
tempo+="$REPLY"$'\n'
done <<< "$pinned"
pinned="${tempo::-1}"
qte_pinned=$( f__wcv "-l" "$pinned" )
if [ "$qte_pinned" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmd_pinned="apt-cache policy | grep '\->'"
cmt_pinned="résultat effectif épinglage paquet"$pluriel
# kernel
#~ meta abandonné, le temps de comprendre ubuntu?
# metaPkg=$( dpkg -l | grep -i -E 'linux-(image|headers)-([0-9]{3}|amd)' )
#~ metaPkg=$( dpkg -l | awk '
#~ /linux-(image|headers)-([0-9]{3}|amd)/ {
#~ printf "%-3s %-30s %s ",$1, $2, $3
#~ $1=$2=$3=$4=""; print $0
#~ }' )
#~ cmd_metaPkg="dpkg -l | grep -i -E 'linux-(image|headers)-([0-9]{3}|amd)'"
#~ cmt_metaPkg="métapaquet noyau"
kernel=$( dpkg -l | awk '
/linux-(headers|image)-'"$(uname -r)"'/ {
printf "%-3s %-30s %s ",$1, $2, $3
$1=$2=$3=$4=""; print $0
}' )
cmd_kernel="dpkg -l | grep -i -E \"linux-(headers|image)-\$(uname -r)\""
cmt_kernel="noyau"
###
f_prnt tit2 "gestion de paquets ${1#*:}"
f_prnt 1 "nombre de paquets installés: **$nb_packages**"
f_prnt 1 "dernière mise à jour apt: **$dateMaj**"
f_prnt 1 "version apt: **$apt_version**"
f_dspl_alrt "$info_update" "info"
f_prnt
f_dspl cmd "$sources" "$cmd_sources" "$cmt_sources"
f_dspl_alrt "$alert_https" "info"
f_dspl_alrt "$alert_httpsPossible" "info"
f_dspl_alrt "$alert_non_list" "info"
f_dspl_alrt "$alert_httpredir" "info"
f_dspl cmd "$apt_prefs" "$cmd_apt_prefs" "$cmt_apt_prefs"
f_dspl_alrt "$alert_non_pref" "info"
f_dspl cmd:vide "$upgrade" "$cmd_upgrade" "$cmt_upgrade"
f_dspl_alrt "$alert_upgrade" "info"
f_dspl_alrt "$alert_apt" "alerte"
f_dspl var "$notUpgraded" " " "$cmt_notUpgraded"
f_dspl_alrt "$alert_full_upgrade" "info"
f_dspl cmd:vide "$toRemove" "$cmd_toRemove" "$cmt_toRemove"
f_dspl_alrt "$alert_remove" "info"
f_dspl cmd:vide "$autoclean" "$cmd_autoclean" "$cmt_autoclean"
f_dspl_alrt "$alert_autoclean" "info"
f_dspl cmd "$clean" "$cmd_clean" "$cmt_clean"
f_dspl_alrt "$alert_clean" "info"
f_dspl cmd:vide "$non_ii" "$cmd_non_ii" "$cmt_non_ii"
f_dspl_alrt "$alert_non_ii" "info"
f_dspl cmd "$deborphan" "$cmd_deborphan" "$cmt_deborphan"
f_dspl_alrt "$alert_deborphan" "info"
f_dspl cmd:vide "$holded" "$cmd_holded" "$cmt_holded"
f_dspl cmd:vide "$pinned" "$cmd_pinned" "$cmt_pinned"
#~ f_dspl cmd "$metaPkg" "$cmd_metaPkg" "$cmt_metaPkg"
f_dspl cmd "$kernel" "$cmd_kernel" "$cmt_kernel"
}
fi_pkg_x(){ # 05/03/2018
local nb_packages cmd_nbPackages sources cmd_sources holded cmd_holded
if [[ ${1%:*} == "dnf" ]]; then # Fedora, RedHat (rpm)
nb_packages=$( LC_ALL=C dnf list installed 2>/dev/null ) # nb_packages=$( f__wcv -l "$( rpm -qa 2>/dev/null )")
nb_packages=${nb_packages#*Installed Packages} # suppression début variable jusqu'à Installed...
cmd_nbPackages="dnf list installed"
sources=$( f_grep_file "/etc/yum.repos.d/*.repo" )
cmd_sources="grep -Ersv '^#|^$' /etc/yum.repos.d/*.repo"
elif [[ ${1%:*} == "pacman" ]]; then # ArchLinux
nb_packages=$( pacman -Q &>/dev/null ) # pas d'exemple de sortie trouvé
cmd_nbPackages="pacman -Q"
sources=$( f_grep_file "/etc/pacman.conf /etc/pacman.d/*" )
cmd_sources="grep -Ersv '^#|^$' /etc/pacman.conf /etc/pacman.d/*"
elif [[ ${1%:*} == "pacman-g2" ]]; then # Frugalware
nb_packages=$( pacman-g2 -Q &>/dev/null ) # pas d'exemple de sortie trouvé
cmd_nbPackages="pacman-g2 -Q"
sources=$( f_grep_file "/etc/pacman.conf /etc/pacman.d/*" ) # coup de bluff
cmd_sources="grep -Ersv '^#|^$' /etc/pacman.conf /etc/pacman.d/*"
elif [[ ${1%:*} == "portage" ]]; then # Gentoo # Sabayon: + Entropy ?
nb_packages=$( emerge -ep world &>/dev/null ) # pas d'exemple de sortie trouvé
cmd_nbPackages="emerge -ep world"
sources=$( f_grep_file "/etc/portage/repos.conf /etc/portage/repos.conf/*" )
cmd_sources="grep -Ersv '^#|^$' /etc/portage/repos.conf /etc/portage/repos.conf/*"
elif [[ ${1%:*} == "slackware" ]]; then # Slackware
nb_packages=$( f__dir -c /var/log/packages )
cmd_nbPackages="ls -1 /var/log/packages/ | wc -l"
sources=$( f_grep_file "/etc/slackpkg/mirrors" )
cmd_sources="grep -Ersv '^#|^$' /etc/slackpkg/mirrors"
elif [[ ${1%:*} == "zypper" ]]; then # Suse, openSuse
nb_packages=$( zypper search --installed-only 2>/dev/null | grep '^i' ) # # nb_packages=$( f__wcv -l "$( rpm -qa 2>/dev/null )")
cmd_nbPackages="zypper search --installed-only"
sources=$( f_grep_file "/etc/zypp/repos.d/*.repo" )
cmd_sources="grep -Ersv '^#|^$' /etc/zypp/repos.d/*.repo"
holded=$( zypper locks 2>/dev/null )
cmd_holded="zypper locks"
elif [[ ${1#*:} == "alps" ]]; then # AryaLinux
nb_packages=$( alps showinstalled &>/dev/null )
cmd_nbPackages="alps showinstalled"
elif [[ ${1#*:} == "eopkg" ]]; then # Solus Linux
nb_packages=$( f__dir -c /var/lib/eopkg/package )
cmd_nbPackages="ls -1 /var/lib/eopkg/package/ | wc -l"
elif [[ ${1#*:} == "Guix" ]]; then # Gnu Guix
nb_packages=$( f__dir -c /gnu/store/*/ )
cmd_nbPackages="ls -1 /gnu/store/*/ | wc -l"
elif [[ ${1#*:} == "lvu" ]]; then # LunarLinux
nb_packages=$( lvu installed 2>/dev/null )
cmd_nbPackages="lvu installed"
elif [[ ${1#*:} == "Nix" ]]; then # NixOs
nb_packages=$( f__dir -c /nix/store/*/ )
cmd_nbPackages="ls -1 /nix/store/*/ | wc -l"
elif [[ ${1#*:} == "opkg" ]]; then # opkg fork ipkg, ipkg (abandonné) sauf sur Syno?
nb_packages=$( opkg list-installed 2>/dev/null )
cmd_nbPackages="opkg list-installed"
elif [[ ${1#*:} == "Sorcery" ]]; then # SourceMage (sorcerer)
nb_packages=$( gaze installed 2>/dev/null )
cmd_nbPackages="gaze installed"
elif [[ ${1#*:} == "tazpkg" ]]; then # SliTaz
nb_packages=$( tazpkg list 2>/dev/null )
cmd_nbPackages="tazpkg list"
elif [[ ${1#*:} == "TinyCoreExtensions" ]]; then # TinyCoreLinux
nb_packages=$( tce-status -i 2>/dev/null )
cmd_nbPackages="tce-status -i"
sources=$( f_grep_file "/opt/tcemirror" )
cmd_sources="/opt/tcemirror"
elif [[ ${1#*:} == "VoidLinux" ]]; then # VoidLinux
nb_packages=$( xbps-query -l 2>/dev/null )
cmd_nbPackages="xbps-query"
sources=$( f_grep_file "/etc/xbps.d/* /usr/share/xbps.d/*" )
cmd_sources="grep -Ersv '^#|^$' /etc/xbps.d/* /usr/share/xbps.d/*"
fi
nb_packages=$( f__wcv -l "$nb_packages" )
[[ -z "$nb_packages" || "$nb_packages" -le 5 ]] && nb_packages="n/a"
[[ ${1#*:} == "Inconnue" ]] && unset nb_packages # totalement inconnu
###
f_prnt tit2 "gestion de paquets ${1#*:}"
f_dspl cmd:text "$nb_packages" "$cmd_nbPackages" "nombre de paquets installés"
f_dspl cmd "$sources" "$cmd_sources" "sources"
f_dspl cmd "$holded" "$cmd_holded" "paquets figés"
f_dspl var "$alert_pkg_todo" "aide souhaitée"
}
fi_reseau(){ # 06/03/2018 ( configuration )
local ip4 gw4 ip4_p ip6 gw6 ip_a route netplan interfaces resolv iwconfig canal_wifi text pluriel
local imgr netmgrinst netmgrrun ipa adr_temp slaac slaac_mac
local alert_ifconfig alert_slaac
declare -A netmgr=(
["NetworkManager"]="/usr/sbin/NetworkManager"
["Wicd"]="/usr/sbin/wicd"
["ConnMan"]="/usr/sbin/connmand"
)
# ipv4
figet_ip "-4"
ip4="$fg_ip"
gw4="$fg_gws"
ip4_p="$fg_ifn_prior"
# ipv6
figet_ip "-6"
ip6="$fg_ip"
gw6="$fg_gws"
# ip a & route
ip_a=$( ip a | sed '/link\/ether/d; /link\/loopback.*/d' ) # filtre adr MAC link (lo)
ip_a=$( sed '/valid_lft forever preferred_lft forever/d;
/temporary deprecated dynamic/d; /preferred_lft 0sec/d' <<< "$ip_a" )
route=$( ip -4 route show | sort )$'\n\n'
route+=$( ip -6 route show )
# netplan (ubuntu)
netplan=$( f_grep_file "etc/netplan/*.yaml" )
# interfaces & resolv
interfaces=$( f_grep_file "/etc/network/interfaces*" )
interfaces=$( sed -E 's/wpa-psk [[:graph:]]+/wpa-psk <WPA key removed>/; s/:/: /' <<< "$interfaces" )
resolv=$( f_grep_file "/etc/resolv.conf" "notitre" )
# iwconfig (/sbin)
iwconfig=$( LC_ALL=C iwconfig 2>/dev/null ) #paquet wireless-tools requis
# iwlist (/sbin) canal wifi utilisé paquet wireless-tools requis
canal_wifi=$( LC_ALL=C iwlist chan 2>/dev/null | grep 'Current Frequency' | grep -Eio 'channel [0-9]+' )
# manager réseaux
for imgr in "${!netmgr[@]}"; do
if [ -e "${netmgr[$imgr]}" ]; then
netmgrinst+="$imgr "
fi
if ps -e | grep -iq "$imgr" ; then
netmgrrun+="$imgr "
fi
done
netmgrinst=${netmgrinst% } # suppression dernier espace
netmgrrun=${netmgrrun% } # suppression dernier espace
[ "$netmgrinst" == "$netmgrrun" ] && unset netmgrinst
# alertes
if type -p ifconfig &>/dev/null ; then
alert_ifconfig="ifconfig [net-tools](https://github.com/giftnuss/net-tools) est un projet abandonné "
alert_ifconfig+="depuis des années. iproute2 (linuxfoundation) le remplace."
fi
# slaac ipv6
for ipa in $ip6 ; do
if grep -q 'ff:fe:' <<< "$ipa"; then
adr_temp=$( grep -o '^.*ff:fe:.* (.*$' <<< "$ipa" )
adr_temp=${adr_temp%/*}
slaac+="$adr_temp"$'\n'
adr_temp=${adr_temp#*: }
slaac_mac+=${adr_temp/ff:fe:}
fi
done
if [ "$slaac" ]; then
if [ "$( f__wcv -l "$slaac" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
slaac_mac=${slaac_mac% ø } # suppression dernier ' ø '
slaac=${slaac%[[:cntrl:]]} # suppression dernier $'\n'
alert_slaac="adresse$pluriel ipv6 autoconfigurée$pluriel (mode SLAAC): \n"
alert_slaac+="$slaac\n"
alert_slaac+="mais adresse$pluriel MAC ($slaac_mac) visible$pluriel. cela permet potentiellement de "
alert_slaac+="suivre et de tracer ce PC sur les réseaux. \n"
alert_slaac+="à vérifier si cet état est souhaité."
fi
###
f_prnt tit2 "configuration"
f_prnt code
f_prnt l1 "ipv4"
f_prnt l2 "$ip4" '[ "$ip4" ]'
f_prnt
if [ "$(f__wcv "-l" "$gw4")" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l2 "passerelle$pluriel: ${gw4//$'\n'/ ⊗ }" '[ "$gw4" ]'
f_prnt
figet_ip "-6"
f_prnt l1 "ipv6"
f_prnt l2 "$ip6" '[ "$ip6" ]'
f_prnt
if [ "$(f__wcv "-l" "$gw6")" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l2 "passerelle$pluriel: ${gw6//$'\n'/ ⊗ }" '[ "$gw6" ]'
f_prnt
if [ "$(f__wcv "-w" "$fg_ifn_prior")" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l1 "interface$pluriel sortante$pluriel:"
f_prnt l2 "ipv6: $fg_ifn_prior" '[ "$fg_ifn_prior" ]' # proto -6 dernier appel à figet_ip
f_prnt l2 "ipv4: $ip4_p" '[ "$ip4_p" ]'
f_prnt code
f_prnt
f_prnt 1 "les adresses Mac peuvent être affichées avec \`$DIRNAME""getInfo --mac\`"
f_prnt 1 "l'IP publique peut être connue avec: \`$DIRNAME""getInfo --ip\`"
f_prnt
# ipv6 dépréciées
f_prnt code "" '[ "$fg_ip_deprec" ]'
f_prnt l1 "ipv6 dépréciées" '[ "$fg_ip_deprec" ]'
f_prnt l2 "$fg_ip_deprec" '[ "$fg_ip_deprec" ]'
f_prnt code "" '[ "$fg_ip_deprec" ]'
f_prnt
# ip a & route & interface & resolv
f_dspl cmd "$ip_a" "ip address"
f_dspl cmd "$route" "ip route show"
f_dspl cmd "$netplan" "grep -EHrsv '#|^$' etc/netplan/*.yaml" "netplan ubuntu"
f_dspl cmd "$interfaces" "grep -EHrsv '#|^$' /etc/network/interfaces*" "configuration manuelle"
f_dspl cmd "$resolv" "cat /etc/resolv.conf" "serveurs de noms DNS utilisés"
# iwconfig & iwlist
f_dspl cmd "$iwconfig" "/sbin/iwconfig 2>/dev/null" "état carte wifi"
f_dspl cmd "$canal_wifi" "/sbin/iwlist chan | grep 'Current Frequency' | grep -Eio 'channel [0-9]+'" \
"canal wifi utilisé"
f_prnt 1 "la configuration ssid utilisée peut être connue (si NetworkManager installé) avec \n \`$DIRNAME""getInfo --ssid\`" '[ "$iwconfig" ]'
f_prnt
# network manager
f_prnt 1 "gestionnaire de réseau" '[ "$netmgrrun" ]'
if [ "$( wc -w <<< "$netmgrinst" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt 2 "installé$pluriel: **$netmgrinst**" '[ "$netmgrinst" ]'
f_prnt 2 "en fonctionnement: **$netmgrrun**" '[ "$netmgrrun" ]'
f_prnt 2 "non trouvé parmi: ${!netmgr[*]}" '[ -z "$netmgrrun" ]'
f_prnt flush
f_dspl_alrt "$alert_ifconfig" "info"
f_dspl_alrt "$alert_slaac" "info"
}
fi_serial(){ # 06/03/2018
local chassis_serial machineId text
(( x_disk == 1 )) || figet_disk
(( x_batt == 1 )) || figet_batt
chassis_serial=$( cat /sys/class/dmi/id/chassis_serial 2>/dev/null )
[ "$chassis_serial" ] || chassis_serial="n/a"
machineId=$( cat /etc/machine-id 2>/dev/null )
[ "$machineId" ] || machineId="n/a"
###
f_prnt tit1 "$BOLD""ID MAchine $BLUE$machineId$STD"
f_prnt
f_prnt 1 "$BOLD""N° Série:$STD"
f_prnt
f_prnt 2 "${GREEN}Disques:"
f_prnt l3 "$BLUE$fg_disk_serial$STD" '[ "$fg_disk_serial" ]'
f_prnt
f_prnt 2 "${GREEN}Batteries:"
f_prnt l3 "$BLUE$fg_batt_serial$STD"
f_prnt
f_prnt 2 "${GREEN}Chassis:"
f_prnt l3 "$BLUE$chassis_serial$STD"
echo -e "$text\n"
}
fi_ssid(){ # 06/03/2018
local nm_ssid text
local file_output="/tmp/$RANDOM-$RANDOM" # ré-assigne sortie pour f_dspl
if [ "$EUID" -ne 0 ]; then
f__info "vous devez être$RED ROOT$BLUE pour installer ce script dans le système"
f__sudo "exec $0 --ssid"
return $?
fi
type -p nmcli &>/dev/null || f__error "NetworkManager requis"
# connexion wifi?
/sbin/iwconfig 2>/dev/null | grep -iq ssid || f__error "pas de connexion wifi"
nm_ssid=$( f_grep_file "/etc/NetworkManager/system-connections/*" "lignevide" )
###
f__info "${RED}Attention:$BLUE la clé du réseau wifi est visible"
f_prnt tit1 "configuration(s) ssid networkmanager"
f_dspl cmd "$nm_ssid" "grep -Ersv '#|^$' /etc/NetworkManager/system-connections/*"
f_prnt flush
f_prnt_md "$file_output" "marge"
rm "$file_output"
}
# shellcheck disable=SC2010
# SC2010 Don't use ls | grep. Use a glob ... to allow non-alphanumeric filenames.
fi_system(){ # 08/03/2018
local mbr uname bootImage initDaemon upstart date_install lastboot uptime uptimePure loadAverage pluriel text
local enum_batt nb_desktop serverX serverType
local alimentation alim_total
# appels fonctions externes
(( x_architecture == 1 )) || f__architecture
(( x_audio == 1 )) || fi_audio "silent"
(( x_batt == 1 )) || figet_batt
(( x_bluez == 1 )) || fi_bluez "silent"
(( x_cpu == 1 )) || figet_cpu
(( x_de == 1 )) || figet_de
(( x_disk == 1 )) || figet_disk
(( x_distrib == 1 )) || figet_distrib
(( x_dm == 1 )) || figet_dm
(( x_dmi == 1 )) || figet_dmi
(( x_gpu == 1 )) || fi_gpu "silent"
(( x_net == 1 )) || fi_net "silent"
(( x_screen == 1 )) || figet_screen
(( x_shell == 1 )) || figet_shell
(( x_touchpad == 1 )) || fi_touchpad "silent"
(( x_wm == 1 )) || figet_wm
[ "$1" != "rc" ] && echo -n "ø"
# divers système
if [ -d /sys/firmware/efi ]; then
mbr="EFI"
else
mbr="Legacy (mbr)"
fi
uname=$( uname -rmo )
bootImage=$( awk '{print $1}{i=2; while (i <= NF) { print " ",$i; i++}}' /proc/cmdline )
initDaemon=$( ps -p1 -o comm --no-headers ) # ps -p1 | awk 'FNR==2 {print $4}'
if [ "$initDaemon" == "systemd" ] && type -p systemd &>/dev/null; then
initDaemon=$( systemd --version | head -n1 )
if [ "$fg_dm" == "slim" ]; then
alert_slim="SLiM est abandonné et n'est pas entièrement compatible avec systemd. voir la page archlinux sur slim"
fi
fi
initDaemon=${initDaemon^} # 1er car mal
if upstart --version &>/dev/null; then # encore présent sur 16.04??
upstart=$( upstart --version | head -n1 )
fi
while read -r; do
date_install=$REPLY
done <<< "$( ls -dlt --time-style '+FORMAT %d/%m/%Y' /home/ /root/ /bin/ /lib* )"
[[ "$date_install" =~ .*([0-9]{2}/[0-9]{2}/[0-9]{4}).* ]] && date_install=${BASH_REMATCH[1]}
# lastboot="$( last -n 1 --time-format iso reboot | awk 'FNR==1 {sub(/T/," ",$5);print $5}' )" # remis à jours en début de mois ?!!
lastboot=$( date -r /var/run/utmp '+%d/%m/%Y %H:%M %z' )
uptimePure="OUI" # si pas vide, pas d'affichage des valeurs Zéro (avec unité) dans uptime
uptime=$(
LC_ALL=C uptime 2>/dev/null | awk -v uptimePure="$uptimePure" -F'( |,|:)+' '{
# extraction selon format de sortie
if ( $7 ~ /^day/ && $9 ~ /^min/ ) { j=$6; h=0; m=$8 } # up 25 days, 30 min,
else if ( $7 ~ /^day/ ) { j=$6; h=$8; m=$9 } # up 25 days, 21:30,
else if ( $7 ~ /^min/ ) { j=0; h=0; m=$6 } # up 15 min,
else { j=0; h=$6; m=$7 } # up 12:30,
if ( j > 1 ) { pluriel="s" }
# 3 parties à afficher ou pas
groupe1 = sprintf( "%d jour%s", j,pluriel )
groupe2 = sprintf( "%02d h", h )
groupe3 = sprintf( "%02d mn", m )
# sortie
if ( uptimePure != "" ) {
printf ( j != 0 ) ? "%s " : "" , groupe1
printf ( h != 0 ) ? "%s " : "" , groupe2
printf ( m != 0 ) ? "%s" : "" , groupe3
} else {
print groupe1,groupe2,groupe3
}
}' )
loadAverage=$(
LC_ALL=C uptime 2>/dev/null | awk -v threads="$fg_nb_threads" -F'(, )' '{
gsub(/ load average: /,"")
if ( threads > 1 ) th="threads"; else th="thread"
la1 = $(NF-2)
la5 = $(NF-1)
la15 = $NF
print "charge système depuis les 1, 5 et 15 dernières minutes:", la1, la5, la15, " "
printf "%s %s %s %s", "soit avec", threads, th, ":"
printf "%d%% %d%% %d%% %s", la1/2*100, la5/2*100, la15/2*100, "d\047occupation du système (en temps)"
}' )
# nombre de bureau
nb_desktop=$( xprop -root 2>/dev/null | grep '^_NET_NUMBER_OF_DESKTOPS.*=' )
nb_desktop=${nb_desktop#* = }
# server X
if [ "$fe_Xorg" ]; then
serverX+="$fe_Xorg"
fi
serverType=" ${XDG_SESSION_TYPE^}" # retourne Wayland ou X11 (mir?)
if ps -e | grep -q 'unity-system-co' ; then # ps -ef | grep unity-system-compositor
serverType="Mir"
fi
if [[ "$serverType" =~ X11 ]]; then
serverType+=":"
fi
if [[ "$serverX" == " " && "$ENV_DISPLAY" ]]; then
serverX+=":no DISPLAY"
fi
if [[ "$serverX" == " " && "$ENV_SSH" ]]; then
serverX+=":ssh"
fi
if [ "$serverX" == " " ]; then
serverX="n/a"
fi
# alimentation
if ls -1 "/sys/class/power_supply/" | grep -iq '^AC' ; then
alim_total=$( grep -cs '1' /sys/class/power_supply/AC*/online )
alimentation=$( awk -v "alim_total=$alim_total" '
{ alim_on=sprintf("%d", $1); if (alim_on>1) pllo="s" }
END { if ( alim_total > 1 ) pllt="s"; printf alim_total " alimentation" pllt
if ( alim_total != alim_on ) print ", " alim_on " branchée" pllo; else print "" }
' /sys/class/power_supply/AC*/online )
fi
# batterie(s)
enum_batt=$( grep -E '[A-Z][A-Z]' <<< "$fg_batt" )
###
if [ "$operation" == "rc" ]; then
fi_system_rc
return
fi
[ "$ORIGIN" ] && f_prnt tit2 "système"
f_prnt
f_prnt 1 "$( sed -E 's/(.*)/**\1** /' <<< "$fg_dmi" )" # en gras
f_prnt
f_prnt 1 "CPU"
f_prnt 2 "**$( sed -n '1p' <<< "$fg_cpu" )**"
f_prnt 1 "Vidéo"
f_prnt 2 "$( sed -E 's/(.*)/**\1**/' <<< "$fe_gpu" )" '[ "$fe_gpu" ]'
f_prnt 2 "pas de carte graphique détectée" '[ "$fe_nb_gpu" -eq 0 ]'
f_prnt 1 "Réseau"
f_prnt 2 "$( sed -E 's/(.*)/**\1**/' <<< "$fe_cards_reseau" )" '[ "$fe_cards_reseau" ]'
f_prnt 2 "pas de carte réseau détectée" '[ "$fe_nb_reseau" -eq 0 ]'
f_prnt 1 "Audio"
f_prnt 2 "$( sed -E 's/(.*)/**\1**/' <<< "$fe_cards_audio" )" '[ "$fe_cards_audio" ]'
f_prnt 2 "pas de carte réseau détectée" '[ "$fe_nb_audio" -eq 0 ]'
f_prnt
f_prnt code
f_prnt l1 "$fg_distrib"
f_prnt l2 "$uname"
f_prnt l2 "boot: $mbr"
f_prnt l2 "architecture système: $fu_archi"
f_prnt l2 "installation: $date_install"
f_prnt l2 "démon init: $initDaemon"
f_prnt l3 "$upstart" '[ "$upstart" ]'
f_prnt l2 "shell actif: $fg_shell"
if [ "$( f__wcv -w "$fg_shells" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l2 "shell$pluriel installé$pluriel: $fg_shells"
f_prnt l2 "$bootImage"
f_prnt
f_prnt l1 Environnement
f_prnt l2 "serveur d'affichage$serverType $serverX"
f_prnt l2 "nombre d'écrans: $fg_nb_screen"
if [ "$( f__wcv "-wv" "$fg_resolution" "pixels" )" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l2 "résolution$pluriel: $fg_resolution"
f_prnt l2 "display manager: $fg_dm"
f_prnt l2 "desktop (DE): $fg_de"
f_prnt l2 "panel: $fg_de_panel" '[ "$fg_de_panel" ]'
f_prnt l2 "window manager: $fg_wm"
f_prnt l2 "nombre de bureaux: $nb_desktop" '[ "$nb_desktop" ]'
f_prnt
f_prnt l1 Matériel
if [ "$fg_nb_cpu" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l2 "$fg_nb_cpu processeur$pluriel $fg_cpu_arch"
if [ "$fe_nb_bluez" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f_prnt l2 "$fe_nb_bluez carte$pluriel bluetooth détectée$pluriel ($fe_cards_bluez)" '[ "$fe_nb_bluez" -gt 0 ]'
f_prnt l2 "$alimentation" '[ "$alimentation" ]'
if [ "$fg_nb_batt" -gt "1" ]; then pluriel="s"; else unset pluriel; fi
f_prnt l2 "$fg_nb_batt batterie$pluriel présente$pluriel:" '[ "$fg_batt" ]'
f_prnt l3 "$enum_batt" '[ "$fg_batt" ]'
if [ "$fe_nb_touchpad" -gt "1" ]; then pluriel="s"; else unset pluriel; fi
f_prnt l2 "$fe_nb_touchpad pavé$pluriel tactile$pluriel:" '[ "$fe_touchpad" ]'
f_prnt l3 "$fe_touchpad" '[ "$fe_touchpad" ]'
f_prnt code
f_prnt
f_prnt 1 "$( sed -E 's/^(.*: )(.*)/\1**\2**/' <<< "$fg_disk_part_fix_tot" )" '[ "$fg_disk_part_fix_tot" ]'
f_prnt 1 "dernier boot: **$lastboot**, il y a **$uptime**"
f_prnt 1 "$loadAverage"
f_prnt flush
f_dspl_alrt "$alert_slim" "alert"
}
fi_system_analyse(){ # 06/03/2018
type -p systemd &>/dev/null || return 0 # pas systemd
local bootTime cmd_bootTime cmt_bootTime pluriel text
local srvcFail cmd_srvcFail cmt_srvcFail qte_srvcFail isrvc srvcFail_list info_services
local bootBlame cmd_bootBlame cmt_bootBlame bootCritic cmd_bootCritic cmt_bootCritic
local bootGraph cmd_bootGraph cmt_bootGraph file="/tmp/getInfo-graph.svg"
local alert_srvcFail
# durée du précédent boot
bootTime=$( LC_ALL=C systemd-analyze time )
bootTime=${bootTime/Startup finished in /Durée de boot: }
bootTime=${bootTime/userspace/espace utilisateur}
cmd_bootTime="systemd-analyze time"
cmt_bootTime="durée du boot, avant interface graphique"
# services en erreur
srvcFail=$( LC_ALL=C systemctl --state=active,failed | awk '
/error|not-found|failed/ { sub(/●|\*/,"");
printf "%-50s %-11s %-8s %-8s %s",$1,$2,$3,$4,$5; $1=$2=$3=$4=$5=""; print $0}' )
cmd_srvcFail="systemctl --state=active,failed | grep -E 'error|not-found|failed'"
qte_srvcFail=$( f__wcv -l "$srvcFail" )
if [ "$qte_srvcFail" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
cmt_srvcFail="service$pluriel en erreur"
if [ "$qte_srvcFail" -gt 0 ]; then
alert_srvcFail="service$pluriel en erreur, statut: \n\n"
srvcFail_list=$( awk '{print $1}' <<< "$srvcFail" )
for isrvc in $srvcFail_list; do
alert_srvcFail+="\`systemctl status $isrvc\` \n"
alert_srvcFail+='```\n'
alert_srvcFail+="$( systemctl status "$isrvc" 2>&1 ) \n"
alert_srvcFail+='```\n'
done
alert_srvcFail=${alert_srvcFail//●}
srvcFail=$( printf "%-50s %-11s %-8s %-8s %s" Unit Load Active Sub Description )$'\n'"$srvcFail"
fi
info_services="voir tous les services: **systemctl list-units --type=service | pager**"
# détail par service
bootBlame=$( LC_ALL=C systemd-analyze blame | head -n 20 )
cmd_bootBlame="systemd-analyze blame | head -n 20"
cmt_bootBlame="détail par service"
# services critiques ralentisseurs
bootCritic=$( LC_ALL=C systemd-analyze critical-chain )
bootCritic=${bootCritic/The time after the unit is active or started is printed after the \"@\" character./ @: temps auquel l\'unité est active ou démarrée}
bootCritic=${bootCritic/The time the unit takes to start is printed after the \"+\" character./ +: temps que l\'unité prend pour démarrer}
cmd_bootCritic="systemd-analyze critical-chain"
cmt_bootCritic="services critiques ralentisseurs"
# génération graphique
if [[ "$wayland" && "$EUID" -eq 0 ]]; then # évite erreur $DISPLAY en root wayland
bootGraph="n/a en root sous wayland"
else
[ -w "$file" ] || file="/tmp/getInfo-graph-$RANDOM.svg"
touch "$file" 2>/dev/null
systemd-analyze plot > "$file" 2>/dev/null
chown "$fu_user": "$file"
bootGraph="en console: **xdg-open $file** \n"
bootGraph+="* dans un navigateur: copier/coller ce lien dans la barre d'adresses "
bootGraph+="file:///$file \n" # résultat avec 4 /, ok
fi
# un lien local ne s'ouvrira pas automatiquement :( : http://kb.mozillazine.org/Links_to_local_pages_do_not_work
cmd_bootGraph="systemd-analyze plot > $file ; xdg-open graph.svg"
cmt_bootGraph="graph durées et ordre de chargement des services"
###
f_prnt tit2 "analyse boot systemd"
f_prnt 1 "pas de service en erreur" '[ -z "$srvcFail" ]'
f_dspl cmd "$bootTime" "$cmd_bootTime" "$cmt_bootTime"
f_dspl cmd "$srvcFail" "$cmd_srvcFail" "$cmt_srvcFail"
f_dspl_alrt "$info_services" "info"
f_dspl_alrt "$alert_srvcFail" "alert"
f_dspl cmd "$bootBlame" "$cmd_bootBlame" "$cmt_bootBlame"
f_dspl cmd "$bootCritic" "$cmd_bootCritic" "$cmt_bootCritic"
f_dspl cmd:text "$bootGraph" "$cmd_bootGraph" "$cmt_bootGraph"
}
fi_system_rc(){ # 12/03/2018
local if_actif iip ip_act
if_actif=$( ip -o link | awk '/state UP/{sub(/:/,"",$2); printf "%s ",$2}' )
for iip in $if_actif; do
ip_act+=$( ip -o address show dev "$iip" | awk '
#~ /inet/ { sub(/wl.*/,"wifi: "$2,$2); sub(/en.*|eth.*/,"rj45: "$2,$2); sub(/\/.*/,"", $4) }
/inet/ { sub(/\/.*/,"", $4) }
/inet6/ { ip6 = $4; exit }
/inet / { ip4 = $4 }
END { printf "%s %s %s",$2,ip4,ip6 }' )
done
f_prnt code
f_prnt 2 "$GREEN$( sed -n '1p' <<< "$fg_dmi" )$STD"
f_prnt 2 "$( sed -n '1p' <<< "$fg_cpu" )"
f_prnt 2 "$fe_gpu"
if grep -q 'wl.*' <<< "$ip_act"; then
toPrint=$( grep 'Wireless:' <<< "$fe_cards_reseau" )$'\n'" $(grep 'wl.*' <<< "$ip_act" )"
f_prnt l2 " * ${toPrint/Wireless: }"
fi
if grep -Eq 'en.*|eth.*' <<< "$ip_act"; then
toPrint=$( grep 'Ethernet:' <<< "$fe_cards_reseau" )$'\n'" $(grep -E 'en.*|eth.*' <<< "$ip_act" )"
f_prnt l2 " * ${toPrint/Ethernet: }"
fi
f_prnt
f_prnt l2 "distrib: $fg_distrib (installation: $date_install)"
f_prnt l2 "kernel : $uname"
f_prnt l2 "boot: $mbr, init: $initDaemon $upstart"
f_prnt l2 "shell : $fg_shell"
f_prnt l2 "serveur d'affichage$serverType $serverX"
f_prnt l2 "nombre d'écrans: $fg_nb_screen"
f_prnt l2 "résolution$pluriel: $fg_resolution"
f_prnt l2 "display manager: $fg_dm"
f_prnt l2 "desktop (DE) : $fg_de"
f_prnt l2 "window manager : $fg_wm"
f_prnt
f_prnt l3 "$fg_disk_part_syst"
f_prnt l3 "dernier boot: $lastboot ($uptime)"
loadAverage=$(
LC_ALL=C uptime 2>/dev/null | awk -v threads="$fg_nb_threads" -F'(, )' '{
gsub(/ load average: /,"")
if ( threads > 1 ) th="threads"; else th="thread"
la1 = $(NF-2)
la5 = $(NF-1)
la15 = $NF
printf "charge système: %s %s %s, ", la1, la5, la15
printf "soit avec %d %s : %d%% %d%% %d%% ", threads, th, la1/2*100, la5/2*100, la15/2*100
}' )
f_prnt l3 "$loadAverage"
f_prnt code
f_prnt flush
}
# [$1=silent], assigne $fe_touchpad, fe_nb_touchpad
fi_touchpad(){ # 06/03/2018
local device cmd_device toScrut xfile file_logs type type_pt pilote cmd_pilote cmt_pilote info_driver
x_touchpad=1
unset fe_touchpad
fe_nb_touchpad=0
device=$( grep -Ei -B1 -A8 'touchpad|trackpoint|synaptics|alps|etps|elan' /proc/bus/input/devices ) || return 0
while read -r; do
REPLY=${REPLY#*Name=\"} # suppression début
REPLY=${REPLY%\"} # suppression fin
fe_touchpad+="$REPLY "$'\n'
done <<< "$( grep -i 'Name=' <<< "$device" )"
fe_touchpad=${fe_touchpad%$'\n'} # suppression \n final
cmd_device="grep -Ei -B1 -A8 'touchpad|trackpoint|synaptics|alps|etps|elan' /proc/bus/input/devices"
# recherche Xorg.log
toScrut=(
/var/log/Xorg.0.log
/home/$fu_user/.local/share/xorg/Xorg.0.log
/var/lib/gdm3/.local/share/xorg/Xorg.0.log
)
for xfile in "${toScrut[@]}"; do
[ -e "$xfile" ] && file_logs+="$xfile "
done
[ "$file_logs" ] || file_logs="nologs"
if [ "$file_logs" != "nologs" ]; then
type=$( grep -is 'touchpad: buttons:' $file_logs )
# essai détection multitouch
grep -iq 'left' <<< "$type" && type_pt="non multitouch"
grep -iq 'double' <<< "$type" && type_pt="2"
grep -iq 'triple' <<< "$type" && type_pt+="3"
grep -iq '[0-9]' <<< "$type" && type_pt=" multitouch $type_pt points"
type_pt=${type_pt/23/ 2\/3}
fe_touchpad+="$type_pt"
fi
fe_nb_touchpad=$( f__wcv -l "$fe_touchpad" )
[[ "$1" == "silent" ]] && return 0
###
if [ "$ENV_DEBIAN" ]; then
pilote=$( dpkg -l | grep -E 'synaptics|libinput' | awk '
/^ii/ { printf "%-30s", $2; $1=$2=$3=$4=""; print $0 }' )
cmd_pilote="dpkg -l | grep -E 'synaptics|libinput'"
cmt_pilote="paquets installés"
info_driver="consulter d'éventuels fichiers *synaptics *libinput dans /etc/X11/xorg.conf.d/ "
info_driver+="pour voir les configurations personnalisées"
fi
###
f_prnt tit2 "touchpad"
f_prnt 1 "$( sed -E 's/(.*)/**\1** /' <<< "$fe_touchpad" )" # mise en gras
f_prnt
f_prnt l1 "Multitouch non détecté" '[ -z "$type_pt" ]'
f_prnt
f_dspl cmd "$device" "$cmd_device"
f_dspl cmd "$pilote" "$cmd_pilote" "$cmt_pilote"
f_dspl_alrt "$info_driver" "info"
}
fi_usb(){ # 05/03/2018
local lsusb size lsusb_t ls lst ils motif result ls_p device id
lsusb=$( lsusb )
[ "$lsusb" ] || return 0
lsusb=$( sort <<< "$lsusb" )
lsusb=$( f_lifting "$lsusb" ) # cosmétique
# largeur max initiale de lsusb
# formation index bus-device de lsub
# 1-1 | 1d6b:0002 Linux Foundation 2.0 root hub
ls=$( awk '{
bus=sprintf("%d",$2)
device=sprintf("%d",$4)
id=sprintf("%s",$6)
$1=$2=$3=$4=$5=$6=""
sub(/^[[:blank:]]*/,"",$0)
periph=$0
printf "%03d-%03d | %s %s\n",bus,device,id,periph
}' <<< "$lsusb" )
# extraction Class Driver de lsusb -t et formation index bus-device
# 1-1 | root_hub ehci-pci/8p
lsusb_t=$( lsusb -t )
lst=$( awk '
BEGIN {FS=", "}
{
sub(/^.*Bus /,"",$1)
sub(/Human Interface Device/,"HID")
sub(/\(Defined at Interface level\)/,"Defined Interf")
sub(/Vendor Specific Class/,"Vend. Specific")
sub(/Application Specific Interface/,"App. Specific")
split($1,tab,".Port [0-9]+: Dev ")
if ( tab[1] ~ /[0-9]+/ ) bus=sprintf("%d",tab[1]); else bus=bus
device=tab[2]
if ( $2 ~ /If/) {
sub(/Class=/,"",$3)
class=$3
sub(/.*Driver=/,"",$4)
driver=$4
} else {
sub(/Class=/,"",$2)
class=$2
sub(/.*Driver=/,"",$3)
driver=$3
}
printf( "%03d-%03d | %-14s %s\n",bus,device,class,driver )
}' <<< "$lsusb_t" )
IFS=$'\n'
# calcul largeur max $ls
size=$(( 0 ))
for ils in $ls; do
if [ ${#ils} -gt "$size" ]; then
size=$(( ${#ils} ))
fi
done
# assemblage et suppression index bus-device
for ils in $ls; do
motif=${ils% |*} # extraction bus-device
result=$( grep -w -m1 "$motif" <<< "$lst" ) # extraction ligne correspondante dans lst
result=${result#* | } # suppression bus-device
ls_p+=$( printf "%-""$size""s %s" "$ils" "$result" )$'\n' # assemblage
done
ls_p=${ls_p%[[:cntrl:]]}
ls_p=${ls_p//|}
ls_p=${ls_p//-/ }
ls_p=$( printf "%s %s %6s %28s %17s %17s" bus dev id périphérique class driver )"\n$ls_p"
IFS="$IFS_INI"
###
f_prnt tit2 "USB"
f_dspl cmd "$ls_p" "lsusb + lsusb -t" "affichage modifié, ajout Class & Driver"
}
fi_vrms(){ # 06/03/2018
local vrms non_free contrib text pluriel tempo
type -p vrms &>/dev/null || return 0
vrms=$( vrms )
non_free=$(( $( sed -En 's/([0-9]+) non-free packages,.*/\1/p' <<< "$vrms" ) ))
contrib=$(( $( sed -En 's/([0-9]+) contrib packages,.*/\1/p' <<< "$vrms" ) ))
if [[ "$non_free" -gt 0 || "$contrib" -gt 0 ]]; then
if [ "$non_free" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
vrms=$( sed -E "s/Non-free packages installed on.*/$non_free paquet$pluriel non libre$pluriel installé$pluriel:/
" <<< "$vrms" )
if [ "$contrib" -gt 1 ]; then pluriel="s"; else unset pluriel; fi
vrms=$( sed -E "s/Contrib packages installed on.*/$contrib paquet$pluriel contrib installé$pluriel:/
" <<< "$vrms" )
vrms=$( sed -E '/[0-9]+ non-free packages,/d; /[0-9]+ contrib packages,/d;
/^[[:space:]]*$/d' <<< "$vrms" )
elif grep -iq 'proud' <<< "$vrms" ; then
tempo="Aucun paquet non libre ou contrib installé sur ce système \n\t\t **rms serait fier ☺**"
vrms=$( sed -E "s/.*rms would be proud.*/$tempo/" <<< "$vrms" )
fi
###
f_prnt tit2 "paquets non-libres"
f_dspl cmd "$vrms" "vrms" "détection des paquets non libres par RMS"
f_prnt flush
}
# informations batterie(s), assigne $fg_nb_batt $fg_batt $fg_batt_serial
figet_batt(){ # 06/03/2018
local batt_detail batt_unit batt_capa_design batt_capa_full batt_capa_now batt_conso
local batt_volt_min batt_volt_now batt_status batt_cycle alert_batt_alarm
local batt_sante batt_restant tempo batRep ibat uevent
x_batt=1
fg_nb_batt=0
if [ ! -d /sys/class/power_supply ]; then # anciennes interfaces ou inconnu
[ -d /proc/acpi/battery ] && fg_batt="ancienne interface ACPI non gérée (obsolète)"
[ -e /proc/apm ] && fg_batt="anciennes batteries APM non gérées (obolète)"
[ "$fg_batt" ] || fg_batt="répertoire power_supply inaccessible"
return 1
fi
fg_nb_batt=$( grep -is 'Battery' /sys/class/power_supply/*/type | grep -c . )
if [ "$fg_nb_batt" -eq 0 ]; then
return 0
fi
batRep="/sys/class/power_supply/"
unset batt_detail
for ibat in $batRep*; do
grep -qi 'Battery' "$ibat/type" || continue # plus loin si non batterie
[ -e "$ibat/uevent" ] || batt_detail="${ibat#$batRep}: **uevent** inexistant"
[ -e "$ibat/uevent" ] || continue
uevent=$( grep -s . "$ibat/uevent" )
# extractions valeur de calcul selon type
if grep -q 'POWER_SUPPLY_CHARGE_' <<< "$uevent" ; then
batt_unit="mAh"
batt_capa_design=$( awk -F '=' '/POWER_SUPPLY_CHARGE_FULL_DESIGN=/ {printf "%d", $2/1000}' <<< "$uevent" ) # mA
batt_capa_full=$( awk -F '=' '/POWER_SUPPLY_CHARGE_FULL=/ {printf "%d", $2/1000}' <<< "$uevent" ) # mA
batt_capa_now=$( awk -F '=' '/POWER_SUPPLY_CHARGE_NOW=/ {printf "%d", $2/1000}' <<< "$uevent" ) # mA
batt_conso=$( awk -F '=' '/POWER_SUPPLY_CURRENT_NOW=/ {printf "%d", $2/1000}' <<< "$uevent" ) # mA
elif grep -q 'POWER_SUPPLY_ENERGY_' <<< "$uevent" ; then
batt_unit="Wh"
batt_capa_design=$( awk -F '=' '/POWER_SUPPLY_ENERGY_FULL_DESIGN=/ {printf "%.2f", $2/1000000}' <<< "$uevent" ) # W
batt_capa_full=$( awk -F '=' '/POWER_SUPPLY_ENERGY_FULL=/ {printf "%.2f", $2/1000000}' <<< "$uevent" ) # W
batt_capa_now=$( awk -F '=' '/POWER_SUPPLY_ENERGY_NOW=/ {printf "%.2f", $2/1000000}' <<< "$uevent" ) # W
batt_conso=$( awk -F '=' '/POWER_SUPPLY_POWER_NOW=/ {printf "%.2f", $2/1000000}' <<< "$uevent" ) # W
fi
# extractions simples
batt_volt_min=$( awk -F '=' '/POWER_SUPPLY_VOLTAGE_MIN_DESIGN=/ {printf "%.2f", $2/1000000}' <<< "$uevent" ) # V
batt_volt_now=$( awk -F '=' '/POWER_SUPPLY_VOLTAGE_NOW=/ {printf "%.2f", $2/1000000}' <<< "$uevent" ) # V
batt_status=$( awk -F '=' '/POWER_SUPPLY_STATUS=/ {print $2}' <<< "$uevent" )
batt_cycle=$( awk -F '=' '/POWER_SUPPLY_CYCLE_COUNT=/ {print $2}' <<< "$uevent" )
fg_batt_serial=$( awk -F '=' '/POWER_SUPPLY_SERIAL_NUMBER=/ {sub(/^ | $|0/,"",$2); print $2}' <<< "$uevent" )
alert_batt_alarm=$( cat "$ibat/alarm" 2>/dev/null )
if [ "$alert_batt_alarm" == "0" ]; then
unset alert_batt_alarm
else
alert_batt_alarm="$( basename "$ibat" ) ($alert_batt_alarm)"
fi
# calculs
batt_sante=$( awk '$1 != "na" && $2 != "" && $2 != 0 {printf "%.1f", $1/$2*100}' <<< "$batt_capa_full $batt_capa_design" )
if [[ "$batt_status" == "Full" || "$batt_status" == "Unknown" ]]; then
batt_restant="totalement chargée"
elif [ "$batt_status" == "Discharging" ]; then
batt_restant="en décharge, reste approximativement: "
tempo=$( awk '$1+$2 != "" && $2!=0 {print $1*0.9/$2}' <<< "$batt_capa_now $batt_conso" )
elif [ "$batt_status" == "Charging" ]; then
batt_restant="en charge, reste approximativement: "
tempo=$( awk '$1+$2+$3 != "" && $3 != 0 {print ($1-$2)/$3}' <<< "$batt_capa_full $batt_capa_now $batt_conso" )
fi
batt_restant+=$( awk '$1 != "" {printf "%d h %02d mn \n", $1, $1*60%60}' <<< "$tempo" )" "
# mise en forme pour sortie, séparateur milliers
if [ "$batt_unit" == "mAh" ]; then
batt_capa_design=$( printf "%'d" "$batt_capa_design" )
batt_capa_full=$( printf "%'d" "$batt_capa_full" )
batt_conso=$( printf "%'d" "$batt_conso" )
batt_capa_now=$( printf "%'d" "$batt_capa_now" )
fi
# sortie
# ligne 1 && n° série
batt_detail+=${ibat#$batRep}": $( cat "$ibat/manufacturer" 2>/dev/null ) "
batt_detail+="($( cat "$ibat/model_name" 2>/dev/null )) $( cat "$ibat/technology" 2>/dev/null ), "
batt_detail+="$batt_capa_design$batt_unit - $batt_volt_min""V / ${batt_volt_now}V (mini/actuel)"
[ "$( xargs <<< "$fg_batt_serial" )" ] && fg_batt_serial="$batt_detail, n° série: $fg_batt_serial" || fg_batt_serial="n/a"
[ "$batt_cycle" != "0" ] && batt_detail+=", $batt_cycle cycles "$'\n' || batt_detail+=" "$'\n' #ln 1fin
# ligne 2
[ "$batt_capa_full" ] && batt_detail+="pleine charge effective: $batt_capa_full$batt_unit, "
batt_detail+="pleine charge théorique: $batt_capa_design$batt_unit => "
if [[ "$batt_conso" != "0" && "$batt_conso" != "0.00" ]]; then # conso éventuelle
batt_restant+="(consommation en cours: $batt_conso$( sed 's/h//' <<< "$batt_unit" ), "
batt_restant+="charge actuelle: $batt_capa_now$batt_unit)"
fi
[ "$batt_sante" ] && batt_detail+="$batt_sante% (indicateur) "$'\n' #ln 2fin
# ligne 3
[ "$batt_restant" ] && batt_detail+="$batt_restant "$'\n' #ln 3fin
# alertes batterie
# ligne 4 éventuelle (alarme batterie)
[ "$alert_batt_alarm" ] && batt_detail+="**batterie en alarme** $alert_batt_alarm "$'\n' #[ln 4]
# lignes 5 alertes
if [ "$batt_capa_design" == "$batt_capa_full" ] && [ "$batt_volt_min" == "$batt_volt_now" ]; then
batt_detail+="les pleines charges et les voltages sont incohérents, batterie "
batt_detail+="mal gérée ou batterie HS? "$'\n' #[ln 5]
fi
if [ "${batt_sante%.*}" -lt 50 ] && [[ "$batt_status" == "Full" || "$batt_status" == "Unknown" ]]; then
batt_detail+="taux de charge batterie faible (moins de 50%): mauvais état? "$'\n' #[ln 5]
fi
done
if [ "$batt_detail" ]; then
fg_batt=${batt_detail::-1} # suppression dernier $'\n'
fi
if [ -z "$( xargs <<< "$fg_batt_serial" )" ] ; then
fg_batt_serial+="n/a"
fi
}
# assigne $fg_cpu (description cpu), fg_nb_threads, $fg_cpu_arch, $fg_vendor=AMD|Intel, $fg_nb_cpu
figet_cpu(){ # 05/03/2018
local cpuinfo speedNom speedMax speedMin speedCpu descrCpu cpu1 cpu2 cpu3
x_cpu=1
fg_nb_threads=0
fg_nb_cpu=0
cpuinfo="$(cat /proc/cpuinfo)"
# speed
speedNom=$( awk -F ':' '/cpu MHz/ { printf "%.2f", $2/1000;exit }' <<< "$cpuinfo" )
speedMax=$( awk '{ printf "%.2f", $1/1000000 }' /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq 2>/dev/null )
speedMin=$( awk '{printf "%.2f", $1/1000000}' /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq 2>/dev/null )
speedCpu=""
if [ "$speedMin" ]; then
speedCpu+="$speedMin/"
descrCpu+="min/"
fi
if [ "$speedNom" ]; then
speedCpu+="$speedNom"
descrCpu+="nom."
fi
if [[ "$speedMax" && "$speedMax" != "$speedNom" ]]; then
speedCpu+="/$speedMax"
descrCpu+="/max"
fi
if [ "$descrCpu" ]; then
descrCpu="fréq. $descrCpu"
fi
if [ "$speedCpu" ]; then
speedCpu=$( printf "%sGHz" "$speedCpu" )
else
speedCpu=$( awk -F '@' '/model name/ {sub(/^ | $/,"",$2); print $2;exit}' <<< "$cpuinfo" )
fi
# motifs?: Processor Dual-Core Quad-Core Six-Core Eight-Core Core 'with Radeon * Graphics'
# nb proc
fg_nb_cpu=$(
awk -F ':|@' '
/^physical id/ { if ($2+1 != nbCpu) nbCpu=$2+1 }
END { printf "%d",nbCpu }' <<< "$cpuinfo" )
# traitement fg_cpu
cpu1=$(
awk -v "speedCpu=$speedCpu" -v "descrCpu=$descrCpu" -F ':|@' '
/^model name/ { gsub(/\(R\)|\(TM\)|\(r\)|\(tm\)|CPU| width/,"",$2); cpu=$2 }
/^physical id/ { if ($2+1 != nbCpu) nbCpu=$2+1 }
/cpu cores/ { procCore=sprintf("%d",$2); if (procCore>1) pllc="s" }
/siblings/ { procThread=sprintf("%d",$2); if (procThread>1) pllt="s" }
END {
printf nbCpu " x " cpu " (" procCore "core" pllc ", " procThread "thread" pllt;
print ") { " speedCpu " (" descrCpu ") }"
}' <<< "$cpuinfo "
)
cpu2=$(
awk -F ':' '
/^vendor_id/{gsub(/ /,"");gsub(/AuthenticAMD/,"AMD");gsub(/GenuineIntel/,"Intel");vendor=$2}
/^cpu family/{family=$2}
/^model[^ ]/{model=$2}; /^stepping/{rev=$2}
/microcode/ { sub(/^ /,"",$2); microCode=$2 }
END {
code=sprintf("{0x%.2X|0x%.2X}",family,model);
print vendor" famille" family", modèle"model,code", révision" rev ", microcode:" microCode
}' <<< "$cpuinfo"
)
cpu3=$(
awk -F ':' '
/address sizes/ { gsub(/ bits/,"b",$2); sub(/physical/,"physique",$2);
sub(/virtual/,"virtuel",$2); sub(/^ | $/,"",$2); add=$2 }
/cache size/ {gsub(/ /,"",$2); gsub(/B/,"o",$2); gsub(/K/,"k",$2); cache=$2}
/bogomips/ { bogomips=sprintf("%d",$2) }
END { print add ", bogomips: " bogomips ", cache: " cache }' <<< "$cpuinfo"
)
fg_cpu="${cpu1// / } "$'\n'"${cpu2// / } "$'\n'${cpu3// / }
fg_nb_threads=$( grep -c '^processor' <<< "$cpuinfo" )
# arch processeur
[ "$( grep -cm1 'flags.* lm ' /proc/cpuinfo )" -ge 1 ] && fg_cpu_arch="64bits" || fg_cpu_arch="32bits"
# fabricant
fg_vendor=$( grep -m1 '^vendor_id' <<< "$cpuinfo" )
fg_vendor=${fg_vendor#*: } # extraction valeur vendor
fg_vendor=${fg_vendor#*: } # extraction valeur vendor
fg_vendor=${fg_vendor//AuthenticAMD/AMD} # allègement
fg_vendor=${fg_vendor//GenuineIntel/Intel} # allègement
# traitement µarchitecture
(( x_cpu_uarch == 1 )) || figet_cpu_uarch
}
# stockage des flags cpu extraits du kernel, assigne $CPU_FLAGS
figet_cpu_flags(){ # 14/12/2017
x_cpu_flags=1
CPU_FLAGS="
# https://github.com/torvalds/linux/blob/master/arch/x86/include/asm/cpufeatures.h
# 11/2017
## Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0
FPU ⟷ Onboard FPU
VME ⟷ Virtual Mode Extensions
DE ⟷ Debugging Extensions
PSE ⟷ Page Size Extensions
TSC ⟷ Time Stamp Counter
MSR ⟷ Model-Specific Registers
PAE ⟷ Physical Address Extensions
MCE ⟷ Machine Check Exception
CX8 ⟷ CMPXCHG8 instruction
APIC ⟷ Onboard APIC
SEP ⟷ SYSENTER/SYSEXIT
MTRR ⟷ Memory Type Range Registers
PGE ⟷ Page Global Enable
MCA ⟷ Machine Check Architecture
CMOV ⟷ CMOV instructions (plus FCMOVcc, FCOMI with FPU)
PAT ⟷ Page Attribute Table
PSE36 ⟷ 36-bit PSEs
PN ⟷ Processor serial number
CLFLUSH ⟷ CLFLUSH instruction
DTS ⟷ Debug Store
ACPI ⟷ ACPI via MSR
MMX ⟷ Multimedia Extensions
FXSR ⟷ FXSAVE/FXRSTOR, CR4.OSFXSR
SSE ⟷ sse
SSE2 ⟷ sse2
SS ⟷ CPU self snoop
HT ⟷ Hyper-Threading
TM ⟷ Automatic clock control
IA64 ⟷ IA-64 processor
PBE ⟷ Pending Break Enable
## AMD-defined CPU features, CPUID level 0x80000001, word 1 Don't duplicate feature flags which are redundant with Intel!
SYSCALL ⟷ SYSCALL/SYSRET
MP ⟷ MP Capable.
NX ⟷ Execute Disable
MMXEXT ⟷ AMD MMX extensions
FXSR_OPT ⟷ FXSAVE/FXRSTOR optimizations
PDPE1GB ⟷ GB pages
RDTSCP ⟷ RDTSCP
LM ⟷ Long Mode (x86-64)
3DNOWEXT ⟷ AMD 3DNow! extensions
3DNOW ⟷ 3DNow!
## Transmeta-defined CPU features, CPUID level 0x80860001, word 2
RECOVERY ⟷ CPU in recovery mode
LONGRUN ⟷ Longrun power control
LRTI ⟷ LongRun table interface
## Other features, Linux-defined mapping, word 3 This range is used for feature bits which conflict or are synthesized
CXMMX ⟷ Cyrix MMX extensions
K6_MTRR ⟷ AMD K6 nonstandard MTRRs
CYRIX_ARR ⟷ Cyrix ARRs (= MTRRs)
CENTAUR_MCR ⟷ Centaur MCRs (= MTRRs)
## cpu types for specific tunings:
K8 ⟷ Opteron, Athlon64
K7 ⟷ Athlon
P3 ⟷ P3
P4 ⟷ P4
CONSTANT_TSC ⟷ TSC ticks at a constant rate
UP ⟷ smp kernel running on up
ART ⟷ Platform has always running timer (ART)
ARCH_PERFMON ⟷ Intel Architectural PerfMon
PEBS ⟷ Precise-Event Based Sampling
BTS ⟷ Branch Trace Store
SYSCALL32 ⟷ syscall in ia32 userspace
SYSENTER32 ⟷ sysenter in ia32 userspace
REP_GOOD ⟷ rep microcode works well
MFENCE_RDTSC ⟷ Mfence synchronizes RDTSC
LFENCE_RDTSC ⟷ Lfence synchronizes RDTSC
ACC_POWERAMD ⟷ Accumulated Power Mechanism
NOPL ⟷ instructions
ALWAYS ⟷ Always-present feature
XTOPOLOGY ⟷ cpu topology enum extensions
TSC_RELIABLE ⟷ TSC is known to be reliable
NONSTOP_TSC ⟷ TSC does not stop in C states
CPUID ⟷ CPU has CPUID instruction itself
EXTD_APICID ⟷ has extended APICID (8 bits)
AMD_DCM ⟷ multi-node processor
APERFMPERF ⟷ APERFMPERF
NONSTOP_TSC_S3 ⟷ TSC doesn't stop in S3 state
TSC_KNOWN_FREQ ⟷ TSC has known frequency
## Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4
PNI ⟷ SSE-3
PCLMULQDQ ⟷ PCLMULQDQ instruction
DTES64 ⟷ 64-bit Debug Store
MONITOR ⟷ Monitor/Mwait support
DS_CPL ⟷ CPL Qual. Debug Store
VMX ⟷ Hardware virtualization
SMX ⟷ Safer mode
EST ⟷ Enhanced SpeedStep
TM2 ⟷ Thermal Monitor 2
SSSE3 ⟷ Supplemental SSE-3
CID ⟷ Context ID
SDBG ⟷ Silicon Debug
FMA ⟷ Fused multiply-add
CX16 ⟷ CMPXCHG16B
XTPR ⟷ Send Task Priority Messages
PDCM ⟷ Performance Capabilities
PCID ⟷ Process Context Identifiers
DCA ⟷ Direct Cache Access
SSE4_1 ⟷ SSE-4.1
SSE4_2 ⟷ SSE-4.2
X2APIC ⟷ x2APIC
MOVBE ⟷ MOVBE instruction
POPCNT ⟷ POPCNT instruction
TSC_DEADLINE_TIMER ⟷ Tsc deadline timer
AES ⟷ AES instructions
XSAVE ⟷ XSAVE/XRSTOR/XSETBV/XGETBV
OSXSAVE ⟷ XSAVE enabled in the OS
AVX ⟷ Advanced Vector Extensions
F16C ⟷ 16-bit fp conversions
RDRAND ⟷ The RDRAND instruction
HYPERVISOR ⟷ Running on a hypervisor
## VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5
RNG ⟷ RNG present (xstore)
RNG_EN ⟷ RNG enabled
ACE ⟷ on-CPU crypto (xcrypt)
ACE_EN ⟷ on-CPU crypto enabled
ACE2 ⟷ Advanced Cryptography Engine v2
ACE2_EN ⟷ ACE v2 enabled
PHE ⟷ PadLock Hash Engine
PHE_EN ⟷ PHE enabled
PMM ⟷ PadLock Montgomery Multiplier
PMM_EN ⟷ PMM enabled
## More extended AMD flags: CPUID level 0x80000001, ecx, word 6
LAHF_LM ⟷ LAHF/SAHF in long mode
CMP_LEGACY ⟷ If yes HyperThreading not valid
SVM ⟷ Secure virtual machine
EXTAPIC ⟷ Extended APIC space
CR8_LEGACY ⟷ CR8 in 32-bit mode
ABM ⟷ Advanced bit manipulation
SSE4A ⟷ SSE-4A
MISALIGNSSE ⟷ Misaligned SSE mode
3DNOWPREFETCH ⟷ 3DNow prefetch instructions
OSVWOS ⟷ Visible Workaround
IBS ⟷ Instruction Based Sampling
XOP ⟷ extended AVX instructions
SKINIT ⟷ SKINIT/STGI instructions
WDT ⟷ Watchdog timer
LWP ⟷ Light Weight Profiling
FMA44 ⟷ operands MAC instructions
TCE ⟷ translation cache extension
NODEID_MSR ⟷ NodeId MSR
TBM ⟷ trailing bit manipulations
TOPOEXT ⟷ topology extensions CPUID leafs
PERFCTR_CORE ⟷ core performance counter extensions
PERFCTR_NB ⟷ NB performance counter extensions
BPEXT ⟷ data breakpoint extension
PTSC ⟷ performance time-stamp counter
PERFCTR_LLC ⟷ Last Level Cache performance counter extensions
MWAITX ⟷ MWAIT extension (MONITORX/MWAITX)
## Auxiliary flags: Linux defined - For features scattered in various CPUID levels like 0x6, 0xA etc, word 7.
RING3MWAIT ⟷ Ring 3 MONITOR/MWAIT
CPUID_FAULT ⟷ Intel CPUID faulting
CPB ⟷ AMD Core Performance Boost
EPB ⟷ IA32_ENERGY_PERF_BIAS support
CAT_L3 ⟷ Cache Allocation Technology L3
CAT_L2 ⟷ Cache Allocation Technology L2
CDP_L3 ⟷ Code and Data Prioritization L3
HW_PSTATE ⟷ AMD HW-PState
PROC_FEEDBACK ⟷ AMD ProcFeedbackInterface
SME ⟷ AMD Secure Memory Encryption
INTEL_PPIN ⟷ Intel Processor Inventory Number
INTEL_PT ⟷ Intel Processor Trace
AVX512_4VNNIW ⟷ AVX-512 Neural Network Instructions
AVX512_4FMAPS ⟷ AVX-512 Multiply Accumulation Single precision
MBA ⟷ Memory Bandwidth Allocation
## Virtualization flags: Linux defined, word 8
TPR_SHADOW ⟷ Intel TPR Shadow
VNMI ⟷ Intel Virtual NMI
FLEXPRIORITY ⟷ Intel FlexPriority
EPT ⟷ Intel Extended Page Table
VPID ⟷ Intel Virtual Processor ID
VMMCALL ⟷ Prefer vmmcall to vmcall
XENPV ⟷ Xen paravirtual guest
## Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9
FSGSBASE ⟷ {RD/WR}{FS/GS}BASE instructions
TSC_ADJUST ⟷ TSC adjustment MSR 0x3b
BMI1 ⟷ 1st group bit manipulation extensions
HLE ⟷ Hardware Lock Elision
AVX2 ⟷ AVX2 instructions
SMEP ⟷ Supervisor Mode Execution Protection
BMI2 ⟷ 2nd group bit manipulation extensions
ERMS ⟷ Enhanced REP MOVSB/STOSB
INVPCID ⟷ Invalidate Processor Context ID
RTM ⟷ Restricted Transactional Memory
CQM ⟷ Cache QoS Monitoring
MPX ⟷ Memory Protection Extension
RDT_A ⟷ Resource Director Technology Allocation
AVX512F ⟷ AVX-512 Foundation
AVX512DQ ⟷ AVX-512 DQ (Double/Quad granular) Instructions
RDSEED ⟷ The RDSEED instruction
ADX ⟷ The ADCX and ADOX instructions
SMAP ⟷ Supervisor Mode Access Prevention
AVX512IFMA ⟷ AVX-512 Integer Fused Multiply-Add instructions
CLFLUSHOPT ⟷ CLFLUSHOPT instruction
CLWB ⟷ CLWB instruction
AVX512PF ⟷ AVX-512 Prefetch
AVX512ER ⟷ AVX-512 Exponential and Reciprocal
AVX512CD ⟷ AVX-512 Conflict Detection
SHA_NI ⟷ SHA1/SHA256 Instruction Extensions
AVX512BW ⟷ AVX-512 BW (Byte/Word granular) Instructions
AVX512VL ⟷ AVX-512 VL (128/256 Vector Length) Extensions
#Extended state features, CPUID level 0x0000000d:1 (eax), word 10
XSAVEOPT ⟷ XSAVEOPT
XSAVEC ⟷ XSAVEC
XGETBV1 ⟷ XGETBV with ECX = 1
XSAVES ⟷ XSAVES/XRSTORS
## Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:0 (edx), word 11
CQM_LLC ⟷ LLC QoS if 1
## Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:1 (edx), word 12
CQM_OCCUP_LLC ⟷ LLC occupancy monitoring if 1
CQM_MBM_TOTAL ⟷ LLC Total MBM monitoring
CQM_MBM_LOCAL ⟷ LLC Local MBM monitoring
## AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13
CLZERO ⟷ CLZERO instruction
IRPERF ⟷ Instructions Retired Count
## Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14
DTHERM ⟷ Digital Thermal Sensor
IDA ⟷ Intel Dynamic Acceleration
ARAT ⟷ Always Running APIC Timer
PLN ⟷ Intel Power Limit Notification
PTS ⟷ Intel Package Thermal Status
HWP ⟷ Intel Hardware P-states
HWP_NOTIFY ⟷ HWP Notification
HWP_ACT_WINDOW ⟷ HWP Activity Window
HWP_EPP ⟷ HWP Energy Perf. Preference
HWP_PKG_REQ ⟷ HWP Package Level Request
## AMD SVM Feature Identification, CPUID level 0x8000000a (edx), word 15
NPT ⟷ Nested Page Table support
LBRV ⟷ LBR Virtualization support
SVM_LOCK ⟷ SVM locking MSR
NRIP_SAVE ⟷ SVM next_rip save
TSC_SCALE ⟷ TSC scaling support
VMCB_CLEAN ⟷ VMCB clean bits support
FLUSHBYASID ⟷ flush-by-ASID support
DECODEASSISTS ⟷ Decode Assists support
PAUSEFILTER ⟷ filtered pause intercept
PFTHRESHOLD ⟷ pause filter threshold
AVIC ⟷ Virtual Interrupt Controller
V_VMSAVE_VMLOAD ⟷ Virtual VMSAVE VMLOAD
VGIF ⟷ Virtual GIF
## Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16
AVX512VBMI ⟷ AVX512 Vector Bit Manipulation instructions
PKU ⟷ Protection Keys for Userspace
OSPKEOS ⟷ Protection Keys Enable
AVX512_VPOPCNTDQ ⟷ POPCNT for vectors of DW/QW
LA57 ⟷ 5-level page tables
RDPID ⟷ RDPIDinstruction
## AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17
OVERFLOW_RECOV ⟷ MCA overflow recovery support
SUCCOR ⟷ Uncorrectable error containment and recovery
SMCA ⟷ Scalable MCA
"
}
# assigne $fg_uarch
figet_cpu_uarch(){ # 05/03/2018
local var_temp vendor family model
local defaut_model="modèle non répertorié" defaut_family="famille non répertoriée"
local defaut_vendor="fabricant non répertorié"
x_cpu_uarch=1
(( x_cpu == 1 )) || figet_cpu # obtention $fg_vendor
var_temp=$( grep -m1 '^cpu family' /proc/cpuinfo ) # family cpuinfo
var_temp=${var_temp#*: } # extraction valeur family
family=$( printf "%.2X" "$var_temp" ) # conversion hexa family
var_temp=$(grep -m1 '^model' /proc/cpuinfo) # model cpuinfo
var_temp=${var_temp#*: } # extraction valeur model
model=$( printf "%.2X" "$var_temp" ) # conversion hexa model
{
case ${fg_vendor,,} in
*intel*)
case $family in
04) fg_uarch="Intel 80486, 1000 à 600nm";; # arch_x86
05)
case $model in
01 | 02 | 03 | 07) fg_uarch="Intel P5 (Pentium)";; # arch_x86
04 | 08) fg_uarch="Intel P5 (Pentium MMX)";; # arch_x86
09) fg_uarch="Intel Quark";; # arch_x86
*) fg_uarch="Intel $defaut_model";;
esac ;;
0B) fg_uarch="Knights Corner (Xeon Phi)";; # arch_x86?
0F)
case $model in
00 | 01 | 02) fg_uarch="Intel NetBurst (P4)";; # arch_x86?
03 | 04 | 06) fg_uarch="Intel NetBurst (Nocona Prescott)";; # arch_x86?
*) fg_uarch="Intel $defaut_model";;
esac ;;
06)
case $model in
01) fg_uarch="Intel Pentium Pro";; # arch_x86
03 | 04 | 05) fg_uarch="Intel Prescott (Pentium II) 90nm";; # arch_x86
06) fg_uarch="Intel Presler (Pentium II) 65nm";; # arch_x86
07 | 08 | 0A | 0B) fg_uarch="Intel (Pentium III)";; # arch_x86
09 | 15 | 0D) fg_uarch="Intel Dothan (Pentium M) 90nm";; # arch_x86
0E) fg_uarch="Intel Core";; # arch_x86
0F | 16) fg_uarch="Intel Merom (Core2) 65nm";;
17 | 1D) fg_uarch="Intel Penryn (Core2) 45nm";;
1A | 1E | 1F | 2E) fg_uarch="Intel Nehalem 45nm";;
25 | 2C | 2F) fg_uarch="Intel Westmere 32nm";;
2A | 2D) fg_uarch="Intel Sandy Bridge 32nm";;
3A | 3E) fg_uarch="Intel Ivy Bridge 22nm";;
3C | 3F | 45 | 46) fg_uarch="Intel Haswell 22nm";;
3D | 47 | 4F | 56) fg_uarch="Intel Broadwell 14nm";;
4E | 55 | 5E) fg_uarch="Intel Skylake 14nm";;
8E | 9E) fg_uarch="Intel Kaby Lake 14nm";;
# atom
1C | 26) fg_uarch="Intel Atom Bonnell 45nm";;
27 |35 |36) fg_uarch="Intel Atom Saltwell 32nm";;
37 | 4A | 4D | 5A) fg_uarch="Intel Atom Silvermont 22nm";;
4C | 5D | 5F) fg_uarch="Intel Atom Airmont 14nm";;
# Knights-series cores
57) fg_uarch="Intel knights_landing";;
85) fg_uarch="Intel knights_mill";;
*) fg_uarch="Intel $defaut_model";;
esac ;;
*) fg_uarch="Intel $defaut_family";;
esac ;;
*amd*)
case $family in
04) # arch_x86
case $model in
03 | 07 | 08 | 09 | 0A) fg_uarch="AMD Am486";; # années 90
0E | 0F) fg_uarch="AMD Am5x86, 350nm";; # 1995-1999
*) fg_uarch="AMD ?86 $defaut_model";;
esac ;;
05) # arch_x86
case $model in
00 | 01 | 02 | 03) fg_uarch="AMD K5 SSA/5 ou 5k86, 350nm";; # 1996
06 | 07) fg_uarch="AMD K6 350, 250nm";; # 1997-1998
08) fg_uarch="AMD K6-2, 250nm";; # 1998-1999
09 | 0D) fg_uarch="AMD K6-3 Sharptooth, 250, 180nm";; # 1999-2000
*) fg_uarch="AMD K5/K6 $defaut_model";;
esac ;;
06) fg_uarch="AMD K7 Athlon, 250, 180, 130nm, (Classic/T-Bird/Palomino/T-Bred/Barton and Thorton";; # arch_x86 1999-2005
0F) # 2003-?
case $model in
0? | 1?) fg_uarch="AMD K8 Hammer (SledgeHammer), 130-65nm";;
2?) fg_uarch="AMD K8 Hammer (SledgeHammer) (rev.E), 130-65nm";;
4? | 5? | 6? | 7? | C?) fg_uarch="AMD K8 Hammer (SledgeHammer) (rev.F+), 130-65nm";;
*) fg_uarch="AMD K8 Hammer (SledgeHammer) $defaut_model";;
esac ;;
10) fg_uarch="AMD Barcelona K10, 65, 45, 32nm";; # 2007-2012 Agena, Toliman, Thuban, Deneb, Heka, Callisto, Regor, Propus APU: Llano
11) fg_uarch="AMD Turion X2 Ultra/Puma mobile, dérivée K8/K10, 65, 45nm";; # mixture of K8/K10 designs with lower power consumption
12) fg_uarch="AMD Fusion, dérivée K10, 32nm";; # Llano
15)
case $model in
00 | 01) fg_uarch="AMD Bulldozer 1ère génération, 32nm";; # 2011- success to K10,
02 | 1?) fg_uarch="AMD Piledriver (Enhanced Bulldozer) (Bulldozer 2e génération), 32nm";; # 2012- APU: Trinity, Richland
3?) fg_uarch="AMD Steamroller (Bulldozer 3e génération), 28nm";; # 2014- APU: Kaveri
6? | 7?) fg_uarch="AMD Excavator (Bulldozer 4e génération), 28nm";; # 2015- gén. finale APU: Carrizo, Bristol Ridge, Stoney Ridge
*) fg_uarch="AMD Bulldozer, $defaut_model";;
esac ;;
17)
case $model in
*) "AMD Zen, 14nm";; # 2017- APU: Raven Ridge
esac ;;
# basse consommation
14) fg_uarch="AMD Bobcat, 40nm";; # 2011- APU: Desna, Ontario, Zacate
16)
case $model in
0?) "AMD Jaguar 28nm";; # 2013- APU: Kabini, Temash
3?) "AMD Puma ou Puma+ (family 16h 2e génération), 28nm";; # 2014- APU: Beema, Mullins, Puma+ APU: Carrizo-L
*) fg_uarch="AMD family 16h (Jaguar/Puma) $defaut_model";;
esac ;;
*) fg_uarch="AMD $defaut_family";;
esac ;;
*arm*) fg_uarch="ARM (avec quelques processeurs VIA) $defaut_vendor";; # à vérifier, info kernel, récente fonctionnalité 2016?
*centaur*) fg_uarch="Centaur (avec quelques processeurs VIA) $defaut_vendor";;
*cyrix*) fg_uarch="Cyrix $defaut_vendor";;
*nexgen*) fg_uarch="NexGen $defaut_vendor";;
*nsc*) fg_uarch="National Semiconductor $defaut_vendor";;
*rise*) fg_uarch="Rise $defaut_vendor";;
*sis*) fg_uarch="SiS $defaut_vendor";;
*transmeta* | *TMx86*) fg_uarch="Transmeta $defaut_vendor";;
*umc*) fg_uarch="UMC $defaut_vendor";;
*via*) fg_uarch="VIA $defaut_vendor";;
*vortex*) fg_uarch="Vortex $defaut_vendor";;
*) fg_uarch="$defaut_vendor";;
esac
}
[ "$fg_uarch" ] && fg_uarch+=" {0x$family|0x$model}"
}
# assigne $fg_de, $fg_de_panel
figet_de(){ # 06/03/2018 # thanks neofetch
local de="n/a" ps_e version tmp_version
x_de=1
fg_de="n/a"
[ "$ENV_DISPLAY" ] && fg_de+=":no Display"
[ "$ENV_SSH" ] && fg_de+=":ssh"
[[ "$fg_de" =~ : ]] && return 0 # retourne n/a ...
##
de="$XDG_CURRENT_DESKTOP"
de=${de/X-} # Cinnamon
de=${de/Budgie:GNOME/Budgie} # Budgie
if [[ "$wayland" && "$EUID" -eq 0 && -z "$de" ]]; then
fg_de="n/a:wayland root"
return 0
# fallback to using xprop
elif [[ -z "$de" ]]; then
de=$( xprop -root -notype 2>/dev/null )
de=$( grep -E '^KDE_SESSION_VERSION|^_MUFFIN_|^XFCE_' <<< "${de^^}" )
de=${de/KDE_SESSION_VERSION*/kde}
de=${de/_MUFFIN_*/cinnamon}
de=${de/XFCE_*/xfce}
fi
# Mise en forme
if [[ "${de,,}" =~ kde ]]; then # test sur minuscules
de="$de$KDE_SESSION_VERSION"
if type -p plasmashell &>/dev/null; then
# LC_ALL=C kf5-config --version
de+=" ($( plasmashell --version 2>/dev/null ))"
elif type -p kde4-config &>/dev/null; then
tmp_version=$( kde4-config --version &>/dev/null )
tmp_version=${tmp_version#*(KDE }
tmp_version=${tmp_version%)*}
de+=" ($tmp_version)"
fi
elif [[ "${de,,}" =~ tde_full_session ]]; then
de="trinity" # fork kde 3.5
elif [[ "${de,,}" =~ muffin || "${de,,}" =~ cinnamon ]]; then
de=$( cinnamon --version )
de=${de:-cinnamon} # si nul, cinnamon
elif [[ "${de,,}" =~ unity ]]; then
de=$( unity --version )
elif [ "${de,,}" == "xfce" ]; then
version=$( xfce4-about --version | head -n1 )
version=${version#*\(Xfce}
version=${version%\)*}
de="$de$version"
fi
if [ "$de" ]; then
fg_de=${de,,} # minuscule
fg_de=${fg_de^} # caractère 1 en majuscule
fi
###
# panel
ps_e=$( ps -e )
fg_de_panel=$( awk '
#inclus lxpanel, mate-panel, gnome-panel, xfce4-panel, lxqt-panel
/(gnome-shell|kicker|plasma-desktop|plasma-netbook|lxpanel|panel|deepin-dock|ede|sugar|theshell|kicker)$|liri-shell/ { print $NF; exit }
' <<< "${ps_e,,}" )
fg_de_panel=${fg_de_panel^}
}
# $fg_nb_disk : nb disk fixe & amovible, $fg_disk_table : tableau sommaire, fg_disk_serial
# $fg_disk_fixe : liste devices block fixes, $fg_disk_amov : liste devices block amovibles
# $fg_disk_part_fix_tot : espace des partitions fixes montées, fg_disk_part_syst: espace partition système
# $fg_disk_ata, $fg_disk_usb, $fg_disk_mmc, $fg_disk_nvme : liste disk ata, usb...
# $fg_disk_part_fixe_m, $fg_disk_part_amov_m : liste partitions montées, fixes ou amovibles
# $fg_disk_part_swap : liste partitions swap
# $fg_disk_part_fixe_nm, $fg_disk_part_amov_nm : liste partitions non montées, fixes ou amovibles
# shellcheck disable=SC2046,SC2086
# SC2046 Quote this to prevent word splitting
# SC2086 Double quote to prevent globbing and word splitting
figet_disk(){ # 08/03/2018
local idisk size type rev type_disk vendor model serial lsblk
declare -a disk_ls disk_lsblk
x_disk=1
unset fg_disk_fixe fg_disk_amov fg_disk_ata fg_disk_usb fg_disk_mmc fg_disk_nvme
fg_nb_disk=0
# bug ou unicode? printf: caractères accentués diminuent 1 caractère sur arguments suivants, ajouter autant d'espaces
fg_disk_table="$( printf '%-5s %-9s %-6s %-10s %-18s %-6s' "disk" "taille" "type" "vendeur" "modèle" " rév." )"$'\n'
fg_disk_serial="$( printf '%-5s %-10s %-18s %-24s' "disk" "vendeur" "modèle " " n° série" )"$'\n'
for idisk in /sys/block/* ; do # /sys/block/sda ...
idisk=${idisk##*/}
disk_lsblk=( $( lsblk -d -no SIZE,HOTPLUG,REV "/dev/$idisk" ) )
size=${disk_lsblk[0]:-n/a}
type=${disk_lsblk[1]:-n/a}
rev=${disk_lsblk[2]:-n/a}
# ata HITACHI HTS723232A7A364 E3834563HWLWBN
disk_ls=( $( stat -c %N "/dev/disk/by-id/"* | awk -F'/dev/disk/by-id/|-|_' '/'"$idisk"'\047$/ && !/-part/ && !/wwn-/ {gsub(/\047/,"");print $2,$3,$4,$5}' ) )
type_disk=${disk_ls[0]:-n/a}
vendor=${disk_ls[1]:-n/a}
model=${disk_ls[2]:-n/a}
serial=${disk_ls[3]:-n/a}
# bug lsblk, sur disk fixe, sort ata comme vendor
# vendor=$( lsblk -d -no VENDOR "/dev/$idisk" )
# model=$( lsblk -d -no MODEL "/dev/$idisk" )
# serial=$( lsblk -d -no SERIAL "/dev/$idisk" )
size=${size/G/Go}
size=${size/M/Mo}
size=${size/K/ko}
# liste disques fixes ou amovibles
if [ "$type" == "0" ]; then
fg_disk_fixe+="$idisk " # "sda ... sdx"
type="Fixe"
else
fg_disk_amov+="$idisk "
type="Amov"
fi
# liste des disques par type
if [[ "$type_disk" =~ ^ata ]]; then
fg_disk_ata+="$idisk "
elif [[ "$type_disk" =~ ^usb ]]; then
fg_disk_usb+="$idisk "
elif [[ "$type_disk" =~ ^mmc ]]; then
fg_disk_mmc+="$idisk "
elif [[ "$type_disk" =~ ^nvme ]]; then
fg_disk_nvme+="$idisk "
fi
# sorties tables
fg_disk_table+=$( printf '%-5s %-9s %-6s %-10s %-18s %-6s' "$idisk" "$size" "$type" "$vendor" "$model" "$rev")$'\n'
fg_disk_serial+=$( printf '%-5s %-10s %-18s %-24s' "$idisk" "$vendor" "$model" "$serial")$'\n'
done
[ "$fg_disk_table" ] && fg_disk_table=${fg_disk_table::-1} # suppression dernier $'\n'
[ "$fg_disk_serial" ] && fg_disk_serial=${fg_disk_serial::-1} # suppression dernier $'\n'
# nb de disques (fixe+amovible)
fg_nb_disk=$( tr ' ' '\n' <<< "$fg_disk_fixe$fg_disk_amov" | grep -c . )
# séquences partitions fixes, montées (m) et non montées (nm)
lsblk=$( lsblk -no KNAME,MOUNTPOINT $( printf '/dev/%s ' $fg_disk_fixe ) 2>/dev/null )
fg_disk_part_fixe_m=$( awk '/\// {printf "%s ",$1}' <<< "$lsblk" )
fg_disk_part_fixe_nm=$( awk '!/\// && /[0-9]+/ && !/\[SWAP\]/{printf "%s ",$1}' <<< "$lsblk" )
# séquences partitions amovibles, montées (m) et non montées (nm)
lsblk=$( lsblk -no KNAME,MOUNTPOINT $( printf '/dev/%s ' $fg_disk_amov ) 2>/dev/null )
fg_disk_part_amov_m=$( awk '/\// {printf "%s ",$1}' <<< "$lsblk" )
fg_disk_part_amov_nm=$( awk '!/\// && /[0-9]+/ && !/\[SWAP\]/{printf "%s ",$1}' <<< "$lsblk" )
# partitions swap
fg_disk_part_swap=$( lsblk -no KNAME,MOUNTPOINT | awk '/\[SWAP\]/ {printf "%s ",$1}' )
fg_disk_fixe=${fg_disk_fixe:--}
fg_disk_amov=${fg_disk_amov:--}
fg_disk_part_fixe_m=${fg_disk_part_fixe_m:--}
fg_disk_part_swap=${fg_disk_part_swap:--}
fg_disk_part_fixe_nm=${fg_disk_part_fixe_nm:--}
fg_disk_part_amov_m=${fg_disk_part_amov_m:--}
fg_disk_part_amov_nm=${fg_disk_part_amov_nm:--}
# total espaces partitions fixes montées
fg_disk_part_fix_tot="partitions fixes montées (total, utilisé, dispo): "
fg_disk_part_fix_tot+=$( df -h --total --output=size,used,avail $( printf '/dev/%s ' $fg_disk_part_fixe_m ) 2>/dev/null | tail -n-1 )
f__trim "fg_disk_part_fix_tot"
fg_disk_part_fix_tot=$( f__unit_french "$fg_disk_part_fix_tot" )
[ "$fg_disk_part_fix_tot" ] || fg_disk_part_fix_tot="n/a"
# espace partition système
fg_disk_part_syst=$(df -h --output=source,size,used,avail,target | awk '
/\/$/ {gsub(/G/,"Go"); gsub(/M/,"Mo"); gsub(/k/,"ko")
printf "partition système: %s, total: %s, occupé: %s, libre: %s (%d%%)",$1,$2,$3,$4, $4/$2*100}' )
}
# assigne $fg_distrib
figet_distrib(){ # 06/03/2017
local prefix version
x_distrib=1
# priorité /etc/os-release, version officielle systemd
if [ -e "/etc/os-release" ]; then
source "/etc/os-release"
else
source "/usr/lib/os-release"
fi
if [ "$PRETTY_NAME" ] && [ "${PRETTY_NAME,,}" != "Linux" ]; then
fg_distrib="${PRETTY_NAME:-${NAME} ${ID}}" # si PRETTY_NAME null, alors tentative sur NAME et ID
fg_distrib=${fg_distrib//'"'} # suppression "
fi
# essai version sur fichier
version=$( cat /etc/*version 2>/dev/null ) # fichier *version?
[[ $version =~ [0-9.]+ ]] || unset version # qui contient des chiffres
# essai lsb_release, antique méthode
if [ "$fg_distrib" ]; then
if grep -iqs 'microsoft' /proc/version ; then
fg_distrib=$( lsb_release -sd 2>/dev/null )"/windows"
fi
if grep -iqs 'chrome-' /proc/version || [ -f "/dev/cros_ec" ] ; then
fg_distrib=$( lsb_release -sd 2>/dev/null )"/chrome-os"
fi
fi
if [ -z "$fg_distrib" ]; then
fg_distrib=$( lsb_release -sd 2>/dev/null )
fi
# prefix sur nom fichier éventuels *[_-][version|release]
if [ -z "$prefix" ]; then
prefix=$( f__dir -l /etc/*_version | sed -En 's#/etc/(.*)_version#\1#p' )
fi
if [ -z "$prefix" ]; then
prefix=$( f__dir -l /etc/*-version | sed -En 's#/etc/(.*)-version#\1#p' )
fi
if [ -z "$prefix" ]; then
prefix=$( f__dir -l /etc/*-release "os" | sed -En 's#/etc/(.*)-release#\1#p' )
fi
# spécial complément
if [ "$prefix" == "redstar" ]; then
prefix="Red Star OS"
fi
prefix=${prefix^} # 1er caractère majuscule
# final
if [[ "$fg_distrib" && ! "$fg_distrib" =~ $prefix ]]; then # si fg_distrib et ne contient pas prefix
fg_distrib="$prefix - $fg_distrib $( xargs <<< "$version" )"
elif [ -z "$fg_distrib" ] && [ "$prefix" ]; then # si fg_distrib vide et si prefix
fg_distrib="$prefix $( xargs <<< "$version" )"
else
fg_distrib="$fg_distrib $( xargs <<< "$version" )" # utilisation fg_distrib "normal", sans préfixe (compris dans fg_distrib)
fi
fg_distrib=${fg_distrib% } # suppression espace final éventuel
if [ -z "$fg_distrib" ]; then
fg_distrib="${OS^} (distribution indéterminée)"
fi
}
# display manager, assigne $fg_dm (liste éventuelle) ou 'n/a'
figet_dm(){ # 05/03/2018
local dm_list="cdm entranced gdm3 'gdm[^-3]' qingy kdm ldm lightdm lxdm mdm nodm orthos sddm slim startx tint2 wdm xdm"
local idm x11
x_dm=1
fg_dm=""
for idm in $dm_list; do
if ps -e | grep -iqw "$idm" ; then
fg_dm+="${idm} "
elif [[ -e "/var/run/${idm}.pid" || -e "/run/${idm}.pid" || -d "/var/run/$idm/" || -d "/run/$idm/" ]]; then
fg_dm+="${idm} "
fi
done
fg_dm=${fg_dm% } # supression espace final
if [ -z "$fg_dm" ]; then
x11=$( cat /etc/X11/default-display-manager 2>/dev/null )
fg_dm=${x11##*/} # conservation dernier champs ifs '/'
fi
if [ -z "$fg_dm" ]; then
fg_dm=$( systemctl status display-manager 2>/dev/null | grep 'Main PID' )
fg_dm=${fg_dm##* } # conservation dernier champs (ifs ' ')
fg_dm=${fg_dm/\(/} # suppression (
fg_dm=${fg_dm/\)/} # suppression )
fi
# mise en forme finale
if [[ "$fg_dm" == "lightdm" ]]; then
fg_dm=$( lightdm --version 2>&1 )
fi
fg_dm=${fg_dm^} # 1er car maj
[ "$fg_dm" ] || fg_dm="n/a"
}
# informations DMI (firmware partie matériel), assigne $fg_dmi
figet_dmi(){ # 06/03/2018
local product board bios tempo idmi indic1 indic2
local chassis_type=( # type de chassis selon smbios janvier 2017
# http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.1.1.pdf
# DSP0134 version: 3.1.1, janvier 2017, $ 7.4.1 System Enclosure or Chassis Types, table 17
'Other' #01h
'Unknown' #02h
'Desktop' #03h
'Low Profile Desktop' #04h
'Pizza Box' #05h
'Mini Tower' #06h
'Tower' #07h
'Portable' #08h
'Laptop' #09h
'Notebook' #0Ah
'Hand Held' #0Bh
'Docking Station' #0Ch
'All in One' #0Dh
'Sub Notebook' #0Eh
'Space-saving' #0Fh
'Lunch Box' #10h
'Main Server Chassis' #11h
'Expansion Chassis' #12h
'SubChassis' #13h
'Bus Expansion Chassis' #14h
'Peripheral Chassis' #15h
'RAID Chassis' #16h
'Rack Mount Chassis' #17h
'Sealed-case PC' #18h
'Multi-system chassis' #19h
'Compact PCI' #1Ah
'Advanced TCA' #1Bh
'Blade' #1Ch
'Blade Enclosure' #1Dh
'Tablet' #1Eh
'Convertible' #1Fh
'Detachable' #20h
)
x_dmi=1
# ligne1 $product
for idmi in sys_vendor product_name product_version chassis_type; do
tempo=$( cat /sys/class/dmi/id/$idmi 2>/dev/null ) # extraction valeur
tempo=${tempo/x.x*} # ménage
tempo=${tempo/To be filled by O.E.M.} # ménage
tempo=${tempo/Not Specified} # ménage
tempo=$( xargs <<< "$tempo" )
if [ "$idmi" == "chassis_type" ]; then
tempo=" • "${chassis_type[ $(( ${tempo##0} - 1 )) ]} # valeur tableau après mise en forme index
fi
# indic1 pour tester égalité avec $board
[[ "$idmi" == "sys_vendor" || "$idmi" == "product_name" ]] && indic1+="$tempo "
product+="$tempo "
done
unset chassis_type
# ligne2 $board (carte mère) éventuellement pas affiché
for idmi in board_vendor board_name board_version; do
tempo=$( cat /sys/class/dmi/id/$idmi 2>/dev/null )
tempo=$( sed 's/x.xx*//; s/To be filled by O\.E\.M\.//g' <<< "$tempo" | xargs )
# indic2 pour tester égalité avec $product
[[ "$idmi" == "board_vendor" || "$idmi" == "board_name" ]] && indic2+="$tempo "
board+="$tempo "
done
# ligne3 $bios
for idmi in bios_vendor bios_version bios_date; do
tempo=$( cat /sys/class/dmi/id/$idmi 2>/dev/null )
tempo=$( sed 's/x.xx*//; s/To be filled by O\.E\.M\.//g' <<< "$tempo" | xargs )
bios+="$tempo "
done
[ "$product" ] && fg_dmi="$product "$'\n'
[[ "$board" && "$indic1" != "$indic2" ]] && fg_dmi+="$board "$'\n'
[ "$bios" ] && fg_dmi+="$bios "
fg_dmi=$( f_lifting "$fg_dmi" )
}
# infos température et fan via acpi, assigne $fg_hw
# shellcheck disable=SC2010
# SC2010 Don't use ls | grep. Use a glob ... to allow non-alphanumeric filenames.
figet_hw(){ # 05/03/2018
local name labelF inputF labelT inputT critT hystT maxiT fan temp ihw
x_hw=1
if [ ! -d /sys/class/hwmon/ ]; then
fg_hw="gestion acpi hwmon non accessible"
return 1
fi
for ihw in /sys/class/hwmon/* ; do
ihw=${ihw%\*} # fix à la rache, quand /sys/class/hwmon/* est vide, le développement du chemin ne se fait pas (vbox), reste * finale, et erreur sir ls suivants
name=$( cat "$ihw/name" 2>/dev/null )
name=${name:-indéfini} # indéfini si null
## TEMPÉRATURE
if ls "$ihw" | grep -Eq 'temp[0-9]+' ; then # tempX dans un nom de fichier
# extraction label
labelT=$( cat "$ihw"/temp*_label 2>/dev/null | tr ' ' '-' | tr '\n' '/' )
# extraction températures
inputT=$( awk '$0!="" && $0!=0 {printf "%.1f/", $1/1000}' "$ihw"/temp*_input 2>/dev/null )
critT=$( awk '$0!="" && $0!=0 {printf "%.1f/", $1/1000}' "$ihw"/temp*_crit 2>/dev/null )
hystT=$( awk '$0!="" && $0!=0 {printf "%.1f/", $1/1000}' "$ihw"/temp*_crit_hyst 2>/dev/null )
maxiT=$( awk '$0!="" && $0!=0 {printf "%.1f/", $1/1000}' "$ihw"/temp*_max 2>/dev/null )
# suppression doublons
critT=$( echo "$critT" | tr '/' '\n' | sort --unique | tr '\n' '/' )
hystT=$( echo "$hystT" | tr '/' '\n' | sort --unique | tr '\n' '/' )
maxiT=$( echo "$maxiT" | tr '/' '\n' | sort --unique | tr '\n' '/' )
# suppression premier /
critT=${critT#/}
hystT=${hystT#/}
maxiT=${maxiT#/}
# suppression dernier caractère (/) fin (nécessaire si multi-valeurs)
inputT=${inputT%/}
labelT=${labelT%/}
critT=${critT%/}
hystT=${hystT%/}
maxiT=${maxiT%/}
# formation affichage
if [ "$inputT" ]; then
temp+=$( printf "%-8s %s°C %s " "$name" "$inputT" "$labelT" )
[ "$critT" ] && temp+=" (crit: ${critT}°C) "
[ "$hystT" ] && temp+=" (hyst: ${hystT}°C) "
[ "$maxiT" ] && temp+=" (maxi: ${maxiT}°C) "
[ "$temp" ] && temp+=$'\n'
fi
fi
## FAN
if ls "$ihw" | grep -Eq 'fan[0-9]+' ; then # fanX dans un nom de fichier
# extraction label (si existe?)
labelF=$( cat "$ihw"/fan*_label 2>/dev/null | tr ' ' '-' | tr '\n' '/' )
# extraction vitesse fan
inputF=$( cat "$ihw"/fan*_input 2>/dev/null | tr '\n' '/' )
# suppression dernier caractère (/) fin
labelF=${labelF%/}
inputF=${inputF%/}
# formation affichage
if [ "$inputF" ]; then
fan+=$( printf "%-8s %'dt/mn %s " "$name" "$inputF" "$labelF" )$'\n'
fi
fi
done
fg_hw="$temp$fan"
fg_hw=${fg_hw%$'\n'}
}
# $1=-4|-6, assigne $fg_ip, $fg_gws, $fg_ifn, $fg_mac, fg_ip_deprec (ipv6)
figet_ip(){ # 06/03/2018
local target ifn
unset fg_ip fg_ip_deprec fg_gws fg_ifn_prior fg_ifn fg_mac
type -p ip &>/dev/null || return 1
[ "$1" ] && proto="$1" || proto="-4"
# adresses ip
fg_ip=$( ip $proto -o address | awk -v proto="$proto" '
BEGIN { if (proto == -6) larg=41; else larg=16 }
/scope global/ {
sub(/wl.*/,$2" (wifi)",$2); sub(/.*en.*|.*eth.*/,$2" (ethernet)",$2);
printf "%-17s: %-"larg"s ",$2,$4
if (proto == -6) {
match($0,/scope .*\\/); scope=substr($0,RSTART,RLENGTH)
sub(/scope /,"",scope); sub(/\\/,"",scope)
match($0,/preferred_lft .*sec/); lft=substr($0,RSTART,RLENGTH)
sub(/sec/,"s",lft); sub(/preferred_lft/,"lft",lft)
printf "(%s) %s \n",lft,scope }
else printf "\n" }
/fe80::/ {
sub(/wl.*/,$2" (wifi)",$2)
match($0,/scope .* \\/); scope=substr($0,RSTART,RLENGTH); sub(/scope /,"",scope); sub(/ \\/,"",scope)
link=link"\n"sprintf("%-17s: %-22s %s",$2,$4,scope) }
/ lo / { lo=sprintf("%s (loopback) : %s",$2,$4) }
END { printf "%s\n%s",link,lo }
' )
# ipv6, traitemenent adresses dynamiques
if [ "$proto" == "-6" ]; then
fg_ip_deprec=$( sed -n '/temporary deprecated dynamic/p' <<< "$fg_ip" )
fg_ip=$( sed '/temporary deprecated dynamic/d; /preferred_lft 0sec/d' <<< "$fg_ip" )
fi
# passerelles
fg_gws=$( ip $proto route | awk '
BEGIN { if (proto == -6) larg=42; else larg=12 }
/default via/ { printf "%-"larg"s (%s)\n",$3,$5 }
' )
# interface sortante
if [ "$proto" == "-6" ]; then
target=$( ip $proto -o route | awk '/proto ra / { print $1; exit}' )
if [ "$target" ]; then
fg_ifn_prior=$( ip $proto route get "$target" | sed -En 's/.*dev (.*) proto.*src ([0-9a-f:]+).*/\1 (\2)/p' )
fi
else
fg_ifn_prior=$( ip $proto route get 255.255.255.255 | sed -En 's/.*dev (.*) src ([0-9.]+) .*/\1 (\2)/p' )
fi
# ifnames & mac
fg_ifn="" fg_mac=""
for ifn in $( f__dir -l /sys/class/net/ ) ; do
if [ "$ifn" != "lo" ]; then
fg_ifn+="$ifn "
fg_mac+="$ifn: $( cat "/sys/class/net/$ifn/address" )"$'\n'
fi
done
fg_ifn=${fg_ifn% } # suppression dernier espace
fg_mac=${fg_mac%[[:cntrl:]]} # suppression dernier $'\n'
}
# $1=-4|-6, assigne $fg_ip_pub
figet_ip_pub(){ # 08/03/2018
local dig_test ip_test telnet_test iip
list_ip4(){ # testé 11/12/2017
ip_test=( # pas de https
http://whatismyip.akamai.com
http://eth0.me
ipinfo.io/ip # http & https
http://alma.ch/myip.cgi # peu fiable curl
http://checkip.amazonaws.com # peu fiable wget
api.infoip.io/ip # http & https fiable wget
api.ipify.org # http & https fiable wget
http://ipecho.net/plain # peu fiable wget / curl
# http://ipof.in/txt # fail wget
)
dig_test=(
whoami.akamai.net/@ns1-1.akamaitech.net
myip.opendns.com/@resolver1.opendns.com
myip.opendns.com/@resolver2.opendns.com
myip.opendns.com/@resolver3.opendns.com
myip.opendns.com/@resolver4.opendns.com
)
telnet_test=( 212.83.150.199 4.ifcfg.me )
}
list_ip6(){ # testé 11/12/2017
ip_test=(
http://ipv6.whatismyip.akamai.com
ip.tyk.nu # http & https
wgetip.com # http & https
l2.io/ip # http & https peu fiable wget
icanhazip.com # http & https peu fiable wget
http://bot.whatismyipaddress.com # peu fiable wget
https://canhazip.com # peu fiable wget
https://tnx.nl/ip # peu fiable wget
ident.me # http & https peu fiable curl
)
dig_test=(
-6/myip.opendns.com/aaaa/@resolver1.ipv6-sandbox.opendns.com
-6/myip.opendns.com/aaaa/@resolver2.ipv6-sandbox.opendns.com
)
telnet_test=( 2001:bc8:3cc9:100::1 6.ifcfg.me )
}
unset fg_ip_pub
# assignation variables & test connectivité
if [ "$1" == "-4" ]; then
f__test_cnx "-4" || return 1 # test connectivité ipv4
list_ip4
elif [ "$1" == "-6" ]; then
f__test_cnx "-6" || return 1 # test connectivité ipv6
list_ip6
fi
# TELNET
if type -p telnet &>/dev/null && [ -z "$fg_ip_pub" ]; then
for iip in "${telnet_test[@]}"; do
fg_ip_pub=$( telnet "$iip" 23 2>/dev/null )
fg_ip_pub=${fg_ip_pub#*Your IP*is }
[ "$fg_ip_pub" ] && break
done
fi
# DIG
if type -p dig &>/dev/null && [ -z "$fg_ip_pub" ]; then
for iip in "${dig_test[@]}"; do
fg_ip_pub=$( eval dig +short "${iip//\// }" )
[ "$fg_ip_pub" ] && break
done
fi
# WGET
if type -p wget &>/dev/null && [ -z "$fg_ip_pub" ]; then
cmd="wget --quiet --tries=1 -o /dev/null -O - "
for iip in "${ip_test[@]}"; do
fg_ip_pub=$( eval "$cmd" "$iip" )
[ "$fg_ip_pub" ] && break
done
fi
# CURL
if type -p curl &>/dev/null && [ -z "$fg_ip_pub" ]; then
cmd="curl --silent --location --retry 0 "
for iip in "${ip_test[@]}"; do
fg_ip_pub=$( eval "$cmd" "$iip" )
[ "$fg_ip_pub" ] && break
done
fi
# NC
if type -p nc &>/dev/null && [ -z "$fg_ip_pub" ] && [ "$1" == "-4" ]; then
for iip in "${telnet_test[@]}"; do
fg_ip_pub=$( nc "$iip" 23 2>/dev/null )
fg_ip_pub=${fg_ip_pub#*Your IP*is }
[ "$fg_ip_pub" ] && break
done
fi
if [ -z "$fg_ip_pub" ]; then
f__error "il manque une des commandes suivantes:\n" \
"dig / wget / curl / telnet / nc ?\n" \
"ou les ip de test sont devenues défaillantes ?\n" \
"réessayer avant de d'approndir les diagnostiques"
fi
}
# $1=audio|video|net|ethernet|wireless, $2 objet raw|name|module REQUIS: declare -A lspci
# $2=name: device(s) (name) -> assigne ${lspci[name]} ${lspci[nb_card]}
# $2=raw: détail lspci (-nnv) -> assigne ${lspci[card]} [${lspci[prefix_gpu]}]
# $2=module: (module kernel) -> assigne ${lspci[module]} ${lspci[srch_mod]} ${lspci[card]} [${lspci[prefix_gpu]}]
# shellcheck disable=SC2034
# SC2034 foo appears unused. Verify it or export it.
figet_lspci(){ # 07/03/2018
local motif field1 pci slots nb_slots pci modLspci mod_file
if [ "$1" = "audio" ]; then
motif="Audio device|Audio controller|Multimedia audio controller"
elif [ "$1" = "video" ]; then
motif="VGA .* controller|Display controller|3D controller" # |multimedia|Graphic
elif [ "$1" = "net" ]; then
motif="Ethernet controller|Network controller"
elif [ "$1" = "ethernet" ]; then
motif="Ethernet controller"
elif [ "$1" = "wireless" ]; then
motif="Network controller"
fi
# les devices
if [ "$2" == "name" ]; then
unset 'lspci[name]'
while read -r field1 pci; do
pci=${pci%(rev *)}
lspci[name]+="$pci "$'\n'
done <<< "$( lspci | grep -Ei "$motif" )"
lspci[name]=$( f_lifting "${lspci[name]}" )
lspci[name]=${lspci[name]%[[:cntrl:]]} # suppression \n final
lspci[nb_card]=$( grep -cEv '^[[:space:]]*$' <<< "${lspci[name]}" )
return 0
fi
# lspci détaillé RAW (servira à MODULE pour extraire les drivers utilisés)
if [[ "$2" == "raw" || "$2" == "module" ]]; then
unset "lspci[card]"
slots=$( lspci | grep -Ei "$motif" | cut -d" " -f1 )
if ! lspci -nnv &>/dev/null ; then # commande/option indisponible
display="lspci -nnv -s <device> non disponible"
return 1
fi
nb_slots=$( grep -cEv '^[[:space:]]*$' <<< "$slots" )
for pci in $slots; do
if [[ "$1" == "video" && "$nb_slots" -gt 1 ]]; then # multi-cartes graphiques
if type -p optirun &>/dev/null; then
pci=$( optirun lspci -nnv -s "$pci" )
lspci[prefix_gpu]="optirun "
else
pci=$( DRI_PRIME=1 lspci -nnv -s "$pci" )
lspci[prefix_gpu]="DRI_PRIME=1 "
fi
else
pci=$( lspci -nnv -s "$pci" )
fi
pci=${pci/(prog-if*])} # suppression (prog-if...])
pci=${pci/Capabilities: <access denied>[[:cntrl:]][[:blank:]]} # suppression Capabilities: <access denied> (user)
lspci[card]+="$pci"$'\n\n' # double \n pour espace entre card
done
lspci[card]=${lspci[card]%$'\n\n'} # suppression double \n final
fi
# module kernel
if [ "$2" == "module" ]; then
unset "lspci[module]" "lspci[srch_mod]"
[ "${lspci[card]}" ] || return # pas de cards, sortie
# module utilisé
modLspci=$( awk -F ': ' '
/Kernel modules/ {print $2}
' <<< "${lspci[card]}" )
modLspci=${modLspci// /|} # si jamais plusieurs modules ??..
modLspci=${modLspci%|} # si | final
modLspci=${modLspci#|} # si | au début
# modules et emplacement
lspci[module]=$( lsmod | grep -Ew "$modLspci" )
mod_file=$( f_search_ko "$modLspci" )
if [ "$mod_file" ]; then
lspci[module]="${lspci[module]}\n\n$mod_file"
fi
lspci[srch_mod]="$modLspci"
fi
}
# $1=mem|swap [total|notitle|nocoltitle], assigne $fg_mem
# indépendant de procps, affichage plus clair que free, mais résultats identiques
# shellcheck disable=SC2034
# SC2034 foo appears unused. Verify it or export it.
figet_mem(){ # 06/03/2018
local MemTotal MemFree MemAvailable Buffers Cached SReclaimable Shmem MemUsed
local SwapTotal SwapFree SwapCached col a b c MemLibre
while read -r a b c; do
[ "$a" == "MemTotal:" ] && MemTotal="$b" #echo "$a $(( ${b/kB}/1024 ))" ! partie entière !
[ "$a" == "MemAvailable:" ] && MemAvailable="$b"
[ "$a" == "MemFree:" ] && MemFree="$b"
[ "$a" == "Buffers:" ] && Buffers="$b"
[ "$a" == "Cached:" ] && Cached="$b"
[ "$a" == "SReclaimable:" ] && SReclaimable="$b"
[[ "$a" =~ Shmem$|MemShared$ ]] && Shmem="$b" # = free shared
[ "$a" == "SwapTotal:" ] && SwapTotal="$b"
[ "$a" == "SwapFree:" ] && SwapFree="$b"
[ "$a" == "SwapCached:" ] && SwapCached="$b"
done <<< "$(< /proc/meminfo)"
if [ -z "$MemFree" ]; then
fg_mem="debug: pas de calcul mémoire, erreur implémentation bash"
return 1
fi
MemLibre=$(( MemFree+Buffers+Cached+SReclaimable ))
MemUsed=$(( MemTotal - MemLibre ))
SwapUsed=$(( SwapTotal-SwapFree ))
totalTotal=$(( MemTotal+SwapTotal ))
totalUsed=$(( MemUsed+SwapUsed ))
totalAvailable=$(( MemAvailable+SwapFree ))
MemTotal=$( printf '%10s' "$( f__unit_human "$MemTotal" )" )
MemUsed=$( printf '%10s' "$( f__unit_human "$MemUsed" )" )
MemAvailable=$( printf '%10s' "$( f__unit_human "$MemAvailable" )" )
MemFree=$( printf '%10s' "$( f__unit_human "$MemFree" )" )
Buffers=$( printf '%10s' "$( f__unit_human "$Buffers" )" )
Cached=$(( Cached+SReclaimable ))
Cached=$( printf '%10s' "$( f__unit_human "$Cached" )" )
Shmem=$( printf '%10s' "$( f__unit_human "$Shmem" )" )
SwapTotal=$( printf '%10s' "$( f__unit_human "$SwapTotal" )" )
SwapFree=$( printf '%10s' "$( f__unit_human "$SwapFree" )" )
SwapUsed=$( printf '%10s' "$( f__unit_human "$SwapUsed" )" )
SwapCached=$( printf '%10s' "$( f__unit_human "$SwapCached" )" )
totalTotal=$( printf '%10s' "$( f__unit_human "$totalTotal" )" )
totalUsed=$( printf '%10s' "$( f__unit_human "$totalUsed" )" )
totalAvailable=$( printf '%10s' "$( f__unit_human "$totalAvailable" )" )
unset fg_mem
if [[ ! "$*" =~ notitle ]]; then
[[ "$*" =~ nocoltitle ]] || col="mémoire"
fg_mem="$col totale utilisée disponible"$'\n'
fi
if [[ "$*" =~ mem ]]; then
[[ "$*" =~ nocoltitle ]] || col="vive:"
fg_mem+="$col$MemTotal$MemUsed$MemAvailable"$'\n'
fi
if [[ "$*" =~ swap ]]; then
[[ "$*" =~ nocoltitle ]] || col="swap:"
fg_mem+="$col$SwapTotal$SwapUsed$SwapFree"$'\n'
fi
if [[ "$*" =~ total ]]; then
[[ "$*" =~ nocoltitle ]] || col="tot.:"
fg_mem+="$col$totalTotal$totalUsed$totalAvailable"$'\n'
fi
if [ "$fg_mem" ]; then
fg_mem=${fg_mem::-1} # suppression dernier $'\n'
fi
}
# $1=bluetooth, assigne $fg_modules, $fg_mod_motif, fg_srch_mod
figet_modules(){ # 05/03/2018
local modules dir separator mod_ko
if [ "$1" == "bluetooth" ]; then
dir="/lib/modules/$(uname -r)/kernel/drivers/bluetooth" # répertoire à scruter
# recherche modules/formation motif ou liste
separator="|" # séparateur | par défaut
modules=$( f__dir -l "$dir" )
modules=${modules//.ko}
modules=${modules// /|}
modules=${modules%$separator} # suppression dernier séparateur
modules=${modules//$separator/$'\n'}
modules=$( sort <<< "$modules" )
modules=${modules//$'\n'/$separator}
modules=${modules%$separator} # suppression dernier séparateur
fi
# recherche modules chargés
fg_modules="$( lsmod | grep -Ew "$modules" )"
# motif de recherche des modules trouvés dans le kernel
if [ "$modules" ]; then
fg_mod_motif="$modules"
else
unset fg_mod_motif
fi
# extraction 1ère lignes modules chargés = module kernel
fg_srch_mod=$( awk '{ print $1; exit }' <<< "$fg_modules" )
# recherche emplacement modules
mod_ko=$( f_search_ko "$fg_srch_mod" )
if [ "$mod_ko" ]; then
fg_modules="$fg_modules\n\n$mod_ko"
fi
}
# assigne $fg_nb_screen, $fg_resolution. return possible fg_resolution=n/a[:ssh][:no Display][:xrandr absent][:wayland root]
figet_screen(){ # 06/03/2018
x_screen=1
# remplissage infos soucis éventuels, écrasé par résolution quand possible
fg_resolution="n/a"
[ "$ENV_DISPLAY" ] && fg_resolution+=":no Display"
[ "$ENV_SSH" ] && fg_resolution+=":ssh"
type -p xrandr &>/dev/null || fg_resolution+=":xrandr absent"
[[ "$wayland" && "$EUID" -eq 0 ]] && fg_resolution+=":wayland root"
[[ "$fg_resolution" =~ : ]] && return 0 # retourne n/a ... toutes les causes dans $fg_resolution
##
# résolution
fg_resolution=$( xrandr --query 2>/dev/null | awk '
/[0-9]\*/ {gsub(/\*\+/,"",$2); printf "%s pixels (%dHz), ", $1, $2}' )
fg_resolution=${fg_resolution%,*} # suppression ',*' final
# nombre d'écran, xrandr ne retourne pas de nombre correct
if [ "$fg_resolution" ]; then
fg_nb_screen=$( grep -o 'pixels' <<< "$fg_resolution" | grep -c . )
else
fg_resolution="n/a"
fi
}
# assigne $fg_shell, $fg_shells
figet_shell(){ # 06/03/2018 # thanks neofetch
local shell ish
x_shell=1
fg_shell=${SHELL##*/} # suppression jusqu'au dernier /, altern: ps -p $BASHPID -o comm --no-heading
fg_shell=${fg_shell,,}
case ${shell:=$fg_shell} in # shell null, donc assigné avec $fg_shell
bash )
shell=${BASH_VERSION%-*} # 4.4.12(1)-release, suppression -* final
;;
* )
shell=" "$( $SHELL --version 2>/dev/null )
;;
esac
shell=${shell/$fg_shell} # suppression ' nomDuShell'
shell=${shell/, version}
shell=${shell/xonsh\//xonsh }
shell=${shell/options*}
shell=${shell/\(*\)}
shell=${shell/ / } # suppression espace double
fg_shell="${fg_shell^} $shell"
# shells installés détectés
if [ -e "/etc/shells" ]; then
for ish in $( f_grep_file "/etc/shells" "notitre" ); do
fg_shells+=${ish##*/}" " # conservation dernier "champs"
done
fg_shells=${fg_shells% } # suppression espace de fin
fg_shells=$( tr ' ' '\n' <<< "$fg_shells" | sort -u | tr '\n' ' ' ) # tri et suppression doublons
else
fg_shells="n/a"
fi
}
# debian indépendant, assigne $fg_ucode (commentaire), $ucode (paquet deb) & return O|1 (1 si pas d'installation)
figet_ucode(){ # 05/03/2018
local flagRep xfile xfileTest=""
(( x_cpu == 1 )) || figet_cpu
# recherche flags cpu rep_good (besoin réel?)
[ "$( grep -cm1 'flags.*rep_good ' /proc/cpuinfo )" -ge 1 ] && flagRep="rep_good ⟷ rep microcode works well"
# test possible installation
[ "${fg_vendor,,}" == "amd" ] && ucode="amd64-microcode" # si $ucode, µmicorcode possible (amd|intel)
[ "${fg_vendor,,}" == "intel" ] && ucode="intel-microcode"
# test emplacements possibles
amd64=(
/etc/default/amd64-microcode
/etc/modprobe.d/amd64-microcode-blacklist.conf
/lib/firmware/amd-ucode/microcode_amd.bin
)
intel=(
/etc/kernel/preinst.d/intel-microcode
/etc/modprobe.d/intel-microcode-blacklist.conf
/lib/firmware/intel-ucode/
#$( which iucode_tool 2>/dev/null )
)
[[ "${fg_vendor,,}" == "amd" ]] && toScrut=( "${amd64[@]}" ) # array à utiliser selon fabricant
[ "${fg_vendor,,}" == "intel" ] && toScrut=( "${intel[@]}" )
for xfile in "${toScrut[@]}"; do
[ -e "$xfile" ] && xfileTest+="y" # un emplacement, un marqueur
done
if [[ ${#xfileTest} -eq 0 && "$ucode" ]]; then # non installé, possible ($ucode)
fg_ucode="pas de microcode installé bien que existant"
[ "$flagRep" ] && fg_ucode+=", flag Cpu: REP_GOOD"
return 1
elif [[ ${#xfileTest} -eq 0 && -z "$ucode" ]]; then # non installé, non possible
[ "$flagRep" ] && fg_ucode="pas de microcode existant, mais flag Cpu: REP_GOOD ?!" # pas de commentaire sauf si flag
return 0
elif [[ ${#xfileTest} -gt 0 && "$ucode" ]]; then # installé, possible
fg_ucode="microcode installé"
[ "$flagRep" ] && fg_ucode+=", flag Cpu: REP_GOOD" || fg_ucode+=", pas de flag Cpu REP_GOOD"
return 0
elif [[ ${#xfileTest} -gt 0 && -z "$ucode" ]]; then
fg_ucode="microcode: détection défaillante" #installé, non possible ?!
return 0
fi
}
# assigne $fg_wm, contient 'n/a' ou égal 'non trouvé' ou WM
figet_wm(){ # 06/03/2018 base départ neofetch
local id xprop_id wm xprop_root ps_e version compositor
x_wm=1
fg_wm="n/a"
type -p xprop &>/dev/null || fg_wm+=":xprop absent" # pas de xprop, pas de wm?!
[ "$ENV_DISPLAY" ] && fg_wm+=":no Display"
[ "$ENV_SSH" ] && fg_wm+=":ssh"
[[ "$wayland" && "$EUID" -eq 0 ]] && fg_wm+=":wayland root"
[[ "$fg_wm" =~ : ]] && return 0 # retourne n/a ...
## WM
id=$( xprop -root -notype _NET_SUPPORTING_WM_CHECK 2>/dev/null )
id=${id##* } # suppression plus grande chaîne au début jusqu"à ' '
xprop_id=$( xprop -id "$id" -notype 2>/dev/null ) # xprop -id "$id" -notype _NET_WM_NAME
xprop_id=${xprop_id,,} # minuscules
wm=${xprop_id/*_net_wm_name = } # suppression jusqu'à 'name = '
wm=${wm/\"} # suppression premier "
wm=${wm/\"*} # suppression 2e " avec éventuels caractères suivants
if [ -z "$wm" ]; then
xprop_root=$( xprop -root 2>/dev/null )
xprop_root=${xprop_root,,} # tout en minuscule
ps_e=$( ps -e )
ps_e=${ps_e,,} # tout en minuscule
if [[ -z ${xprop_root/*blackbox_pid*/} ]]; then
if [[ -z ${ps_e/*fluxbox*/} ]]; then
wm='fluxbox'
else
wm='blackbox'
fi
elif [[ -z ${xprop_root/*enlightenment*/} ]]; then wm="enlightenment"
elif [[ -z ${xprop_root/*herbstluftwm*/} ]]; then wm="herbstluftwm"
elif [[ -z ${xprop_root/*icewm*/} ]]; then wm="iceWm"
elif [[ -z ${xprop_root/*openbox_pid*/} ]]; then wm="openbox"
elif [[ -z ${xprop_root/*windowmaker*/} ]]; then wm="windowmaker"
elif [[ -z ${ps_e/*afterstep*/} ]]; then wm='afterstep'
elif [[ -z ${ps_e/*awesome*/} ]]; then wm='awesome'
elif [[ -z ${ps_e/*cinnamon*/} ]]; then wm='cinnamon'
elif [[ -z ${ps_e/*compiz*/} ]]; then wm='compiz'
elif [[ -z ${ps_e/*fvwm*/} ]]; then wm='fvwm'
elif [[ -z ${ps_e/*fvwm-crystal*/} ]]; then wm='fvwm-Crystal'
elif [[ -z ${ps_e/*pekwm*/} ]]; then wm='pekwm'
elif [[ -z ${ps_e/*sawfish*/} ]]; then wm='sawfish'
elif [[ -z ${ps_e/*scrotwm*/} ]]; then wm='scrotwm'
elif [[ -z ${ps_e/*spectrwm*/} ]]; then wm='spectrwm'
elif [[ -z ${ps_e/*xfwm4*/} ]]; then wm='xfwm4'
elif [[ -z ${ps_e/*wmii*/} ]]; then wm='wmii'
elif [[ -z ${ps_e/*wmii2*/} ]]; then wm='wmii2'
elif [[ -z ${ps_e/*smithay*/} ]]; then wm='smithay' # aveugle
if [[ "$wm" == +(*wlc|swc|waysome) ]]; then
wm=$( grep -Eo 'sway|orbment|velox|orbital|waysome|loliwm|Way-Cooler|fireplace' <<< "$ps_e" )
fi
elif grep -q "/i3_" <<< "$xprop_root"; then wm="i3"
elif grep -q "/_wm2" <<< "$xprop_root"; then wm="wm2"
elif grep -q "/dwm" <<< "$ps_e"; then wm='dwm'
elif grep -q "/jwm" <<< "$ps_e"; then wm='jwm'
elif grep -q "/twm" <<< "$ps_e"; then wm='twm'
fi
fi
if [ "${wm,,}" == "gnome shell" ]; then
version=$( gnome-shell --version )
version=${version/GNOME Shell}
wm="$wm$version"
elif [ "${wm,,}" == "xfwm4" ]; then
version=$( xfwm4 --version | head -n1 )
version=${version#*version}
version=${version%)*}")"
wm="$wm$version"
fi
## Compositor
if [[ "$xprop_id" =~ marco_version ]]; then # mate, ok
compositor=${xprop_id/*_marco_version = } # suppression jusqu'à ...
compositor=${compositor/\"} # suppression premier"
compositor=${compositor/\"*} # suppression 2e " avec éventuels caractères suivants
compositor="Marco $compositor"
wm=${wm/ (marco)} # suppression (marco) dans wm
fi
if [[ "$xprop_id" =~ mutter_version ]]; then # gnome3 ok
compositor=${xprop_id/*_mutter_version = } # suppression jusqu'à ...
compositor=${compositor/\"} # suppression premier"
compositor=${compositor/\"*} # suppression 2e " avec éventuels caractères suivants
compositor="Mutter $compositor"
fi
if [[ "$xprop_id" =~ muffin_version ]]; then # cinnamon, ok
compositor=${xprop_id/*muffin_version = } # suppression jusqu'à ...
compositor=${compositor/\"} # suppression premier"
compositor=${compositor/\"*} # suppression 2e " avec éventuels caractères suivants
compositor="Muffin $compositor"
wm=${wm/ (muffin)} # suppression (muffin) dans wm
fi
if [[ "$wm" == kwin ]]; then # kde ok
compositor=$( kwin --version )
compositor=${compositor/kwin } # suppression kwin, conservation n° version
fi
if [[ "$wm" =~ sway ]]; then
compositor+=$( sway -v )
fi
if [ -z "$compositor" ]; then
# en aveugle, pour test et adaptations futures
[[ "$xprop_id" =~ compiz ]] && compositor='compiz'
[[ "$xprop_id" =~ compton ]] && compositor+='compton'
[[ "$xprop_id" =~ dwc ]] && compositor+='dwc'
[[ "$xprop_id" =~ fireplace ]] && compositor+='fireplace'
[[ "$xprop_id" =~ gnome-shell ]] && compositor='gnome-shell'
[[ "$xprop_id" =~ grefson ]] && compositor+='grefson'
[[ "$xprop_id" =~ kmscon ]] && compositor+='kmscon'
[[ "$xprop_id" =~ moblin ]] && compositor+='moblin'
[[ "$xprop_id" =~ rustland ]] && compositor+='rustland'
[[ "$xprop_id" =~ sway ]] && compositor+='sway'
[[ "$xprop_id" =~ swc ]] && compositor+='swc'
[[ "$xprop_id" =~ wayhouse ]] && compositor+='wayhouse'
[[ "$xprop_id" =~ westford ]] && compositor+='westford'
[[ "$xprop_id" =~ weston ]] && compositor+='weston'
fi
[ "${compositor,,}" == "${wm,,}" ] && unset wm
# mise en forme finale
if [ "$compositor" == "compiz" ]; then
compositor=$( compiz --version )
fi
wm=${wm^} # 1er caractère en majuscule
compositor=${compositor^} # 1er caractère en majuscule
if [[ "$wm" && "$compositor" ]]; then
fg_wm="$wm ($compositor)"
elif [[ "$wm" ]]; then
fg_wm="$wm"
elif [[ "$compositor" ]]; then
fg_wm="$compositor"
fi
if [ -z "${fg_wm^}" ]; then
fg_wm="non trouvé"
fi
}
# aiguillage export paste, insertion fichier log (debug script)
fipaste(){ # 06/03/2018
if ! f__requis "curl"; then
f__info "une fois Curl installé, inutile de relancer la détection" \
"$GREEN $DIRNAME""getInfo -p" "pour exporter le rapport existant"
return 1
fi
if [ -e "$debug_output" ]; then
echo -e "\n\n# debug script\n" >> "$file_output"
echo '```' >> "$file_output"
cat "$debug_output" >> "$file_output"
echo '```' >> "$file_output"
rm -f "$debug_output"
fi
fipaste_curl_pastery "$file_output" "$pasteDuration" "$optDebug"
# à tester fipaste_curl_markdownshare "$file_output"
}
# $1=fichier à exporter, $2 durée de conservation en jour; $3 debug
fipaste_curl_pastery(){ # 06/03/2018
local curl id pluriel
[ -e "$1" ] || f__error "fichier $1 inexistant"
# curl -X POST "https://www.pastery.net/api/paste/?title=getInfo&language=markdown" -F file=@$1
# un fichier simple curl https://www.pastery.net/api/paste/ -F file=@data.txt
curl=$( curl --silent -X POST "https://www.pastery.net/api/paste/?title=getInfo_$version&language=markdown&duration=$(( $2*1440 ))" --data-binary @"$1" )
if grep -q '"result": "error' <<< "$curl" ;then
f__info "${RED}Erreur critique export rapport:"
f__info "$curl"
else
id=$( echo "$curl" | cut -d '"' -f 4 )
if [ $(( pasteDuration )) -gt 1 ]; then pluriel="s"; else unset pluriel; fi
f__info "votre paste:$GREEN https://www.pastery.net/$id/" \
"(valide pendant $RED$pasteDuration jour$pluriel)"
echo -e "exporté sur https://www.pastery.net/$id/ \n\n" >> "$file_output"
fi
[ "$3" == "debugPaste" ] && f__info "$curl"
# UTF-8
# ?api_key=<api_key>
# &duration=<duration> en mn, 1 jour par défaut
# &language=autodetect possible
# &max_views=<max_views>
# 100ko max
#{"id": "kddgar", "title": "getInfo_2.5.0", "url": "https://www.pastery.net/kddgar/", "language": "markdown", "duration": 1439}
#{"result": "error", "error_msg": "Your request body was not valid UTF-8."}
}
fipaste_curl_markdownshare(){ # à tester/finir
[ -e "$1" ] || f__error "fichier $1 inexistant"
curl -H "Accept: application/json" -X POST -F "text=<$1" https://markdownshare.com/create/
#-A, --user-agent and -e, --referer options
#If you wish to allow a post to expire then add an expire= parameter too:
#expire=Nh Expire in N hours.
#expire=Nd Expire in N days.
#-d expire ? ou --data expire
}
# fonction spécifique à l'installation
fscript_install_special(){ # 08/03/2018
local bashrc
# lanceur dans /usr/bin
echo "#!/bin/bash" > "/usr/bin/gfetch"
echo "$script_install --rc" >> "/usr/bin/gfetch"
chmod +x "/usr/bin/gfetch"
# inscription dans bashrc si trouvé
for ifile in "/etc/bash.bashrc" "/etc/bashrc" "/etc/bash.bashrc.local"; do
if [ -e "$ifile" ]; then
bashrc="$ifile"
break
fi
done
[ "$bashrc" ] || return
grep -q "$script_install --rc" "$bashrc" && return # déjà inscrit
echo -e "\n### add by getInfo" >> "$bashrc"
echo "$script_install --rc" >> "$bashrc"
}
# fonction spécifique à la désinstallation
fscript_remove_special(){ # 03/03/2018
local bashrc
# lanceur
rm -f "/usr/bin/gfetch"
# bashrc
for ifile in "/etc/bash.bashrc" "/etc/bashrc" "/etc/bash.bashrc.local"; do
if [ -e "$ifile" ]; then
bashrc="$ifile"
break
fi
done
sed -i "/$script/d" "$bashrc"
}
# anacron hebdomadaire, via cron horaire, $1=upgrade|install|remove
fscript_cronAnacron(){ # 07/03/2018
local dirAnacron dirSpool fileAnacron
type -t fscript_cronAnacron_special &>/dev/null && fscript_cronAnacron_special # test, si fonction spécifique, appel
dirAnacron="/home/$fu_user/.config/anacron"
dirSpool="$dirAnacron/spool"
fileAnacron="$dirAnacron/$script.anacrontab"
[ "$EUID" -eq 0 ] && sed -i "/$script.anacrontab/d" /etc/crontab
case "$1" in
install | upgrade )
mkdir -p "$dirAnacron"
# table anacron
echo "7 10 $script nice $script_install --upgrade 1>/dev/null" > "$fileAnacron" # juste erreurs en syslog
## anacron journalier pour dev logname
if [ -e "$fileDev" ]; then
echo "1 00 $script""Dev nice $script_install --upgrade 1>/dev/null" >> "$fileAnacron"
fi
# création spool anacron utilisateur
mkdir -p "$dirSpool"
chown -R "$fu_user:" "$dirAnacron" "$dirSpool"
if [ "$EUID" -eq 0 ]; then
# crontab pour activation horaire anacron
echo "@hourly $fu_user /usr/sbin/anacron -t $fileAnacron -S $dirSpool" >> /etc/crontab
fi
grep -q "$script" "/etc/crontab" || echo f__error "inscription crontab"
;;
remove )
rm -f "${dirSpool:?}/$script"* 2>/dev/null
rm -f "$fileAnacron"
rmdir "$${dirSpool:?}" "${dirAnacron:?}" 2>/dev/null
;;
esac
}
# [$1=quiet], assigne $ver_script_install, $ver_script_online, $script_a_jour=ok|KO
# shellcheck disable=SC2120
# SC2120 function references arguments, but none are ever passed. (quiet)
fscript_get_version(){ # 06/03/2018
x_script_get_version=1
# version online
if ! ver_script_online=$( wget -q --timeout=15 -o /dev/null -O - "$url_script" | grep -m1 '^version=' | cut -d'=' -f2 ); then
f__wget_test "$url_script"
fi
# version installée
if [ -e "$script_install" ]; then
ver_script_install=$( grep -m1 '^version=' "$script_install" | cut -d'=' -f2 )
fi
if [[ "$ver_script_online" && "$script_install" ]]; then
[ "$ver_script_install" != "$ver_script_online" ] && script_a_jour="KO" || script_a_jour="ok"
fi
[ "$ver_script_online" ] || ver_script_online="${RED}n/a"
[ "$ver_script_install" ] || ver_script_install="Non installé"
[ "$1" == "quiet" ] && return 0
f__info "raw" "script en place: $GREEN$ver_script_install"
f__info "script en ligne: $YELLOW$ver_script_online"
}
fscript_install(){ # 24/02/2018
if grep -Eq "$script_install|/usr/bin/$script" <<< "$0"; then
f__info "${RED}l'installation dans le système doit se faire depuis le script non installé $GREEN(./$script -i )"
return 1
fi
type -t fscript_install_special &>/dev/null && fscript_install_special # test, si fonction spécifique, appel
f__requis "wget anacron cron" || exit 1
# install /opt
mkdir -p /opt/bin/
cp -d "$0" "$script_install"
ln -s "$script_install" "/usr/bin/$script" &>/dev/null
chmod 775 "$script_install" # rwx rwx r-x, proprio fu_user
# cron/anacron install
fscript_cronAnacron "install"
# création fichier log
touch "$script_logs"
chmod 664 "$script_logs" # rw- rw- r--, proprio fu_user
chown "$fu_user:" "$script_logs" "$script_install"
[ -e "$fileDev" ] || rm -f "$0" ## on efface pas si fileDev (dev)
f__info "log" "$script $version installé dans le système." "maintenant, appel du script par: $GREEN$script$BLUE (sans ./)"
}
fscript_remove(){ # 24/02/2018
if ! grep -Eq "$script_install|/usr/bin/$script" <<< "$0"; then
f__info "${RED}cette fonction doit être appelée depuis le script installé dans le système $GREEN($script -r)"
return 1
fi
if [ ! -x "$script_install" ];then
f__info "$RED$script n'est pas installé"
return 1
fi
type -t fscript_remove_special &>/dev/null && fscript_remove_special # test, si fonction spécifique, appel
# suppression /opt, lien /usr/bin
rm -f "$script_install"
unlink "/usr/bin/$script" &>/dev/null
# cron/anacron remove
fscript_cronAnacron "remove"
f__info "log" "$script $version supprimé du système."
}
# si upgrade en place, $1 != "", [$1 message info]
# shellcheck disable=SC2120
# function references arguments, but none are ever passed.
fscript_update(){ # 09/03/2018
local dirTemp="/tmp/$script-maj" upgradeEnPlace="$1"
type -t fscript_update_special &>/dev/null && fscript_update_special # test, si fonction spécifique, appel
if [ -z "$upgradeEnPlace" ] && ! grep -Eq "$script_install|/usr/bin/$script" <<< "$0"; then
f__info "${RED}cette fonction doit être appelée depuis le script installé dans le système $GREEN($script -u)"
return 1
fi
(( x_script_get_version == 1 )) || fscript_get_version
if [ "$script_a_jour" == "ok" ]; then
f__info "log" "pas de mise à jour disponible pour $script $version"
return 0
else
f__info "mise à jour en cours"
fi
mkdir -p "$dirTemp"
if ! wget -q --tries=2 --timeout=15 -o /dev/null -O "$dirTemp/$script" "$url_script"; then
rm -fr "$dirTemp"
f__wget_test "$url_script"
fi
if grep -q '#!/bin/bash' "$dirTemp/$script" && grep -q '^### END CONTROL' "$dirTemp/$script"; then
cp -d "$dirTemp/$script" "$script_install"
chmod 775 "$script_install" # rwx rwx r-x, proprio fu_user
chown "$fu_user:" "$script_install"
[ -z "$upgradeEnPlace" ] && fscript_cronAnacron "upgrade"
f__info "log" "$script mis à jour en version $ver_script_online $upgradeEnPlace"
else
f_info "log" "$script: échec update" "mauvais téléchargement, réessayer plus tard"
fi
rm -fr "$dirTemp"
}
prg_init(){ # 08/04/2018
PATH='/usr/sbin:/usr/bin:/sbin:/bin'
TERM=xterm
IFS_INI="$IFS"
IFS=$' \t\n'
export PATH TERM IFS
# options bash figées
# défaut bash, pattern étendus: extglob
shopt -s checkwinsize complete_fullquote extglob extquote interactive_comments sourcepath
shopt -u force_fignore execfail failglob
# options bash spé
# shopt -s nocasematch ( case, [[ ), nocaseglob ( fichier )
# test bash v4
[ "${BASH_VERSINFO[0]}" == 4 ] || f__error "bash v4 requis" "version installée: $BASH_VERSION"
# whereis script retourne vide si installé
DIRNAME=$( dirname "$0" )
DIRNAME=${DIRNAME#/usr/bin} # suppression /usr/bin éventuel au début ( lien )
DIRNAME=${DIRNAME#/opt/bin} # suppression /opt/bin éventuel au début ( install )
[ "$DIRNAME" ] && DIRNAME+="/"
# test /proc
if [ ! -e /proc/cpuinfo ]; then
if ! mount | grep -q "type proc"; then
f__error "/proc non monté"
else
f__error "/proc/cpuinfo non trouvé"
fi
fi
# test OS
OS=$(uname -s)
[[ ${OS,,} =~ linux || ${OS,,} =~ gnu ]] && OS="linux"
[[ ${OS,,} =~ bsd || ${OS,,} =~ Bitrig || ${OS,,} =~ DragonFly ]] && OS="bsd"
[[ ${OS,,} =~ cygwin || ${OS,,} =~ msys || ${OS,,} =~ mingw ]] && OS="windows"
[ "$OS" == "bsd" ] && f__info "ce script pour Linux n'est pas prévu de fonctionner sur BSD..."
[ "$OS" == "windows" ] && f__info "ce script pour Linux n'est pas prévu de fonctionner sous windows..."
[ "$OS" != "linux" ] && f__error "Linux requis"
# recherche wayland
if ps -e | grep -iq 'wayland' ; then
wayland="wayland"
elif [ "$WAYLAND_DISPLAY" ]; then
wayland="wayland"
fi
# test SSH
[[ "$SSH_CLIENT" || "$SSH_CONNECTION" || "$SSH_TTY" || ${DISPLAY%:*} ]] && ENV_SSH="ssh"
# test $DISPLAY => $ENV_DISPLAY vide (null) si pas de serveurX
[ -z "$DISPLAY" ] && ENV_DISPLAY="no DISPLAY"
# détermination user derrière root
f__user
retourFUser="$?"
[ "$retourFUser" -eq 1 ] && f__error "user indéterminé" \
"pour contourner, lancer le script avec:\n$GREEN USER_INSTALL=<user> $0 \n"
if [ "$retourFUser" -eq 2 ]; then
if [ "$EUID" -eq 0 ]; then
fu_user="root"
else
f__error "user détecté, mais pas de home: /home/$fu_user"
fi
f__info "user root"
fi
# requis pour fonctionnement programme
f__requis "gawk|mawk>gawk wget ip>iproute2 lspci>pciutils wc>coreutils uptime>procps" || exit 1
# essai évitement awk à la voidlinux (souci avec awk -F ou -F ' | ')
if ! echo 'abc=123' | awk -F '=|:' {} &>/dev/null; then
f__error "awk en place va poser problème." "Pour participer au débuggage, vous pouvez contacter:" "$contact"
fi
# détection rapide systeme deb
type -p dpkg &>/dev/null && ENV_DEBIAN="oui"
# définition couleurs
f__color
}
prg_1(){ # 02/12/2017 début
echo > "$file_output"
chown $fu_user: "$file_output" &>/dev/null
chmod 666 "$file_output" &>/dev/null # rw-rw-rw-, si root permet écriture & effacement à tous
echo -e "* **$script** sur *$(uname -n)* \n" > "$file_output"
echo -e "$ligneRapport \n" >> "$file_output"
echo -e "--- \n" >> "$file_output"
}
prg_2(){ # 08/03/2018 traitements principaux
if [[ "$1" == all || "$1" =~ s ]]; then #systeme, matériel -cs
echo -e "# ▷ Système" >> "$file_output"
for i in fi_system fi_cpu fi_mem fi_hw fi_batt fi_gpu fi_net fi_audio fi_touchpad fi_bluez fi_usb fi_disk ; do
echo -n "•"
[ "$debugScript" == "ok" ] && echo -e "\n$i : " 1>&2
$i
done
fi
if [[ "$1" == all || "$1" =~ c ]]; then #configuration #debian, packages -cc
echo -e "# ▷ Configuration" >> "$file_output"
for i in fi_efi fi_locale fi_conf fi_vrms fi_packagers ; do
echo -n "•"
[ "$debugScript" == "ok" ] && echo -e "\n$i : " 1>&2
$i
done
fi
if [[ "$1" == all || "$1" =~ r ]]; then #reseau -cr
echo -e "# ▷ Réseau" >> "$file_output"
for i in fi_reseau fi_nm ; do
echo -n "•"
[ "$debugScript" == "ok" ] && echo -e "\n$i : " 1>&2
$i
done
fi
if [[ "$1" == all || "$1" =~ a ]]; then #analyse -ca
echo -e "# ▷ Analyse" >> "$file_output"
for i in fi_system_analyse fi_journal_xorg fi_journal ; do
echo -n "•"
[ "$debugScript" == "ok" ] && echo -e "\n$i : " 1>&2
$i
done
fi
echo -e "\n"
if [[ "$1" != all ]]; then
if [ "$DISPLAY" ]; then f_prnt_md "$file_output"; else pager "$file_output"; fi
fi
}
prg_3(){ # 22/02/2018 fin de traitements
echo -e "--- \n" >> "$file_output"
echo -e "$ligneRapport \n" >> "$file_output"
if [ "$debugScript" == "ok" ]; then
echo -e "\n ***** fin script ***** \n" 1>&2
exec 2>&4 # restauration
exec 4>&- # fermeture FD4
fi
f__dialog_oui_non "non clear" "\n exporter sur le pastebin par défaut?" && fipaste
f__info "le rapport est disponible en local, fichier:$YELLOW $file_output" \
"vous pouvez le visualiser ultérieurement avec $GREEN$script -l" \
"vous pourrez aussi l'exporter avec $BLUE$script -p"
}
prg_menu(){ # 08/03/2018
function prg_menu_display { # 06/03/2018
local centre=50 left=2 larg=60
if [ $(( $(tput cols) )) -le 80 ]; then
centre=$(( $(tput cols)/2+left ))
larg=$(( centre+3*left ))
fi
tput cud 1
tput hpa $left
printf '%.'$larg's' "$1"
tput hpa $centre
printf '%.'$larg's' "$2"
}
echo -en " $GREEN$script -h$STD : afficher l'aide \n"
prg_menu_display "$GREEN$script -c${RED}s$STD : catégorie système" \
"$GREEN$script -c${RED}c$STD : catégorie configuration"
prg_menu_display "$GREEN$script -c${RED}r$STD : catégorie réseau" \
"$GREEN$script -c${RED}a$STD : catégorie analyse"
echo -e "\n\n les catégories peuvent être cumulées: \n" \
" $GREEN$script -c${RED}sa$STD générera un rapport sur le système & l'analyse"
echo -en "\n ( ne pas saisir le préfixe $YELLOW-c$STD, all par défaut)\n"
echo -en "\n choix des catégories à générer (all pour toutes)? "
read -r
if [ "$REPLY" ]; then
REPLY="-c${REPLY,,}"
else
REPLY="all"
fi
REPLY=$( sed 's/-call/all/' <<< "$REPLY" )
exec "$0" "$REPLY"
}
######## début script / initialisation
# tests au démarrage
prg_init
# logo et définition couleurs
[ "$1" != "--rc" ] && f_affichage
# paramètres script
user_agent="Mozilla/5.0 Firefox"
fileDev="/opt/bin/fileDev"
file_output="getInfo_rapport.md"
debug_output="/tmp/$script.log"
script_install="/opt/bin/$script"
script_logs="/var/log/sdeb_$script.log"
url_script="https://framagit.org/kyodev/kyopages/raw/master/scripts/$script"
url_notice="https://kyodev.frama.io/kyopages/scripts/getInfo/"
pasteDuration=7 # durée de conservation standard du paste en jours
spc5=$'\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0'
ligneRapport="Rapport du $(date '+%d/%m/%Y %H:%M %z')$spc5$spc5$0 $*$spc5$spc5[$script $version]($url_notice)"
declare -A lspci # sortie figet_lspci
options="$*"
for j in $options; do # première passe options
case $j in
--debug-paste ) # si debug, retour json de pastery.net
optDebug="debugPaste"
;;
--debug ) # enregistrement stderr dans $script.log
debugScript="ok"
echo > "$debug_output"
chmod 666 "$debug_output" &>/dev/null
exec 4>&2 # sauvegarde
exec 2> "$debug_output" # redirection
echo -e "$ligneRapport \n" 1>&2
;;
-t* ) # durée de conservation standard du paste en jours
pasteDuration=$(( $( sed -En 's/-t([0-9]+)/\1/p' <<< "$j" ) ))
;;
-i | --install | -r | --remove | --irc | --rrc ) # root requis si install ou remove script
if [ "$EUID" -ne 0 ]; then
f__info "vous devez être$RED ROOT$BLUE pour cette opération"
f__sudo "exec $0 $*"
exit
fi
;;&
esac
done
options=$( sed -E 's/--debug-paste//g; s/-t[0-9]+//g; s/--debug//g' <<< "$options" | xargs ) # nettoyage options
[ "$options" ] || options="all"
for k in $options; do # traitement options menu catégories
categorie+=$( sed -En 's/-c([a-z]+)/\1/p' <<< "$k" )
options=$( sed -E 's/-c[a-z]+//' <<< "$k" | xargs )
done
[ "$categorie" ] && options+=" -c$categorie"
for j in $options; do # deuxième passe options, actions
case $j in
-t | --test ) # test
ORIGIN='test'
prg_1 "$*"
echo -n "•"
# fi_system fi_cpu fi_mem fi_hw fi_batt fi_gpu fi_net fi_audio fi_touchpad fi_bluez fi_usb fi_disk
# fi_efi fi_locale fi_conf fi_vrms fi_packagers
# fi_reseau fi_nm
# fi_system_analyse fi_journal_xorg fi_journal
fi_system
echo
if [ "$DISPLAY" ]; then f_prnt_md "$file_output"; else pager "$file_output"; fi
;;
-c* | all ) # rapport complet ou par catégorie
[ "$j" == "-c" ] && exec "$0" "menu"
prg_1 "$*"
j=$( sed -E 's/-c//' <<< "$j" )
prg_2 "$j"
prg_3
;;
-dx ) # essai détail, xorgOnly
prg_1 "$*"
fi_gpu "xorgOnly"
if [ "$DISPLAY" ]; then f_prnt_md "$file_output"; else pager "$file_output"; fi
exit ;;
-dp ) # essai util source/apt confOnly
prg_1 "$*"
fi_pkg_apt "confOnly"
if [ "$DISPLAY" ]; then f_prnt_md "$file_output"; else pager "$file_output"; fi
;;
-j ) # analyse, catégorie -ca
prg_1 "$*"
prg_2 "a"
;;
-l ) # afficher le rapport existant
if [ "$DISPLAY" ]; then f_prnt_md "$file_output"; else pager "$file_output"; fi
;;
-p ) # exporte le rapport existant
fipaste
;;
--ip ) # affiche ip public (ipv4&6)
fi_ip_pub
echo
;;
--mac ) # affiche adresses mac
figet_ip
f__info "adresses MAC:\n$STD$BOLD$fg_mac"
;;
--rc ) # gfetch
operation="rc"
file_output="/tmp/getInfo.rc"
echo > "$file_output"
chmod 666 "$file_output" &>/dev/null
fi_system "rc"
f_prnt_md "$file_output"
exit ;;
--serial ) # affiche n° série
fi_serial
;;
--ssid ) # affiche configurations ssid
fi_ssid
;;
-h ) # affichage help
f_help
;;
-i | --install ) # installation script
fscript_install
;;
-r | --remove ) # remove script
fscript_remove
;;
--irc ) # install gfetch only
fscript_install_special
;;
--rrc ) # remove gfetch only
fscript_remove_special
;;
-u | --upgrade ) # upgrade script
operation="upgrade" # log si f__error
fscript_update
exit ;;
-us | --us ) # upgrade spécial (en place)
operation="upgrade" # log quand f__error
script_install=$( dirname "$0" )"/$script"
fscript_update "update en place" # redéfinition répertoire install avec celui du script
exit ;;
-v | --version ) # version du script, en ligne et en place
fscript_get_version
;;
menu | * ) # affichage help
prg_1 "$*"
prg_menu
exit ;;
esac
done
exit 0
### END CONTROL (contrôle chargement)
wget -nv -O getInfo https://frama.link/getinfo
chmod +x getInfo && ./getInfo
wget -nv -O getInfo https://framagit.org/kyodev/kyopages/raw/master/scripts/getInfo