kyopages/scripts/getInfo

4422 lines
179 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
version=3.2.0
date="26/12/2017"
projet="simpledeb"
contact="IRC freenode ##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
}
f__color(){ # 08/10/2017
YELLOW=$(tput setaf 3) # question
GREEN=$(tput setaf 2) # ok
BLUE=$(tput setaf 4) # info
RED=$(tput setaf 1) # alerte
STD=$(tput sgr0) # retour normal
MAGENTA=$(tput setaf 5)
CYAN=$(tput setaf 6)
BOLD=$(tput bold)
ITAL=$(tput sitm)
SOUL=$(tput smul)
}
# $1=oui|non&[-tx] réponse par défaut & -tx=timeout, $2=message question, return 0 pour oui, 1 pour non
f__dialog_oui_non(){ # 12/12/2017
local param
[[ "$1" =~ -t[0-9]{1,2} ]] && param="$(sed -En 's/.*(-t[0-9]{1,2}).*/\1/p' <<< $1)"
echo -en "$BLUE$2$STD"
[[ "$1" =~ oui ]] && echo -n " [O/n] " || echo -n " [o/N] "
if [ "$param" ]; then
read -t2 -r
else
read -r
fi
if [ -z "$REPLY" ]; then
[[ "$1" =~ oui ]] && REPLY="oui" || REPLY="non"
fi
echo
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
# -lc: liste en colonne des noms de fichiers seuls
# si joker (*?) sur chemin, le motif d'exclusion ne s'applique pas à un répertoire listé, juste sur le nom du fichier
# attention, les jokers sont interprétés à l'appel de la fonction
# exemple: f__dir -l "$dir" "lock|partial" ou "\.list"
f__dir(){ # 12/12/2017
local i=0 action="-c" stock=''
[[ "$1" =~ - ]] && action="$1" || action="-c" # si option en erreur: -c
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 "
#echo "$REPLY $i"
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(){ # 26/12/2017
local depart=1 i
[[ "$1" =~ "raw" || "$1" =~ "log" ]] && depart=2
[[ "$1" =~ "log" ]] && f__log "$(sed -E 's/\\t//;s/\\n// ' <<< $2 | xargs )"
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(){ # 4/12/2017
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
}
# test dépendances/paquets, $1 liste commande[>paquet] (ex: killall>psmisc)
# si manque, return 1 & info commandes manquantes, si debian proposition paquet à installer
# si $2=debOnly et si paquets manquants: return 1 et $debOnlyAbsent ( $1=liste paquets )
# si $2=debOnly et si paquets présent: return 0 et $debOnlyPresent ( $1=liste paquets )
# attention priorité $debOnlyAbsent sur $debOnlyPresent
f__requis(){ # 4/12/2017
local dependsMissing packagesMissing command package ireq compteur pluriel
unset debOnlyAbsent debOnlyPresent
for ireq in $1; do
command="$(cut -d '>' -f 1 <<< $ireq)"
package="$(cut -d '>' -f 2 <<< $ireq)"
if [ "$2" == "debOnly" ]; then
if type -p "dpkg" &>/dev/null ; then # package only et debian
LC_ALL=C dpkg --get-selections | grep -qE "^$package[[:space:]]+install" \
&& debOnlyPresent+="$package " || debOnlyAbsent+="$package "
fi
elif ! type -p "$command" &>/dev/null ; then
dependsMissing+="$command "
packagesMissing+="$package "
fi
done
[ "$debOnlyAbsent" ] && debOnlyAbsent="$(xargs <<< $debOnlyAbsent)" # trim début & fin
[ "$debOnlyPresent" ] && debOnlyPresent="$(xargs <<< $debOnlyPresent)" # trim début & fin
[ "$debOnlyAbsent" ] && return 1
[ "$debOnlyPresent" ] && return 0
if [ "$dependsMissing" ]; then
compteur="$(wc -w <<< $dependsMissing)"
[ "$compteur" -gt "1" ] && pluriel="s" || unset pluriel
if [ -e /etc/debian_version ]; then
f__info "$RED""erreur critique: $compteur paquet"$pluriel" manquant"$pluriel": $STD$BOLD$dependsMissing" \
"\n vous devriez exécuter:$GREEN apt install $packagesMissing"
else
f__info "$RED""erreur critique: $compteur commande"$pluriel" manquante"$pluriel": $STD$BOLD$dependsMissing"
fi
return 1
fi
}
# $1=cmd si $2: nb de tentatives pour s'identifier, sinon 2 tentatives par défaut, suppose bash existant
f__sudo(){ # 23/12/2017
local nb=2 sudo isudo toBash
type -p bash &>/dev/null && toBash=$( type -p bash ) || return 2
# sudo --shell bash équivalent su ?
if sudo -v &>/dev/null && [ $EUID -ne 0 ] ; then
sudo="sudo su --shell $toBash --preserve-environment -c "
else
sudo="su --shell $toBash --preserve-environment -c "
fi
[ "$2" ] && nb=$(( "$2" ))
for (( isudo=1 ; isudo<="$nb" ; isudo++ )); do
$sudo " $1"
[ "$?" == 0 ] && break
[ "$isudo" == "$nb" ] && return 1
done
}
# $1=nombre à convertir en ko, affiche ko ou Mo ou Go, ! dépendance gawk
f__unit_human(){ # 5/12/2017
echo -n "$( gawk ' {
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(){ # 3/12/2017
local user userid test 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)"
elif grep -qEo '[0-9]+' <<< "$XAUTHORITY" ; then
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 grep -qv 'root' <<< "$(who)"; then
user="$(grep -v 'root' <<< $(who) | head -n1 | cut -d ' ' -f1)"; # grep -v 'root' <<< $(who) | gawk 'FNR==1{print $1}'
elif grep -q 'hourly.*get[A-Z].*\.anacrontab.*\.config/anacron/spool' /etc/crontab; then
user="$(grep 'hourly.*get[A-Z].*\.anacrontab.*\.config/anacron/spool' /etc/crontab | head -n1 | cut -d' ' -f2)"; # grep 'hourly.*get[A-Z].*\.anacrontab.*\.config/anacron/spool' /etc/crontab | gawk 'FNR==1{print $2}
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/11/2017
[[ "$1" =~ -l|-wv|-w ]] || display="erreur f__wcv \$1 ($1) incorrect \n"
[ "$1" == "-l" ] && echo "$2" | grep -cEv '^[[:space:]]*$' # (wc -l compterait 1 pour une variable vide)
[ "$1" == "-w" ] && echo "$(xargs <<< $2) " | grep -o " " | grep -c . # echo $(( $(grep -c .)+1 ))
[ "$1" == "-wv" ] && echo "$2" | grep -o "$3" | grep -c .
}
# 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(){ # 24/12/2017
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"
else
echo -e "$BLUE $1$STD\t$GREEN $retourHttp"
fi
echo "$STD"
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
}
# $1=commande à tester, return localisation cmd si existe, return 1 si absent avec aucun message (à là debian)
# pour un test concis genre [ "$(f__which $cmd)" ] && echo "$cmd existe"
# utilisation `type -p` pour le test, pour une bonne portabilité
f__which(){ # 27/11/2017
if type -p "$1" &>/dev/null ; then
echo $( type -p $1 2>/dev/null ) # équivalent: command -v
else
return 1
fi
}
f_affichage(){ # 2/12/2017
local affichage_text=" _ ___ __
__ _ ___| |_|_ _|_ __ / _| ___
/ _' |/ _ \ __|| || '_ \| |_ / _ \
| (_| | __/ |_ | || | | | _| (_) |
\__, |\___|\__|___|_| |_|_| \___/
|___/ "
clear
echo -e "$BLUE$affichage_text\n$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)
# f_dspl "variable" "type" "titre" "commentaire"
f_dspl(){ # 14/12/2017
local display='' toDisplay
[ "$text" ] && echo -en "$text" >> "$fileOutput" # flush, avant fonction, de $text parent
unset text
[[ "$2" || "$1" =~ :vide ]] || return 0 # test si contenu dans $2
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 $2 non trouvé \n"
elif [[ "$1" =~ :text || "$toDisplay" == "vide" ]]; then
display+="\n* $toDisplay \n"
else
display+='``` \n'
display+="$toDisplay \n"
display+='``` \n\n'
fi
echo -en "$display" >> "$fileOutput"
}
# $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(){ # 14/12/2017
[ "$1" ] || return 0 # test si contenu dans $1
local display type
# flush, avant fonction, de $text parent
[ "$text" ] && echo -en "$text\n" >> "$fileOutput"
unset text
[[ "$2" =~ info ]] && type="info"
[[ "$2" =~ alert ]] && type="alert"
[ "$2" ] || type="alert" # alert par défaut
[ "$type" == "alert" ] && display="> ↯ $1 \n"
[ "$type" == "info" ] && display="$1 \n"
echo -en "$display" >> "$fileOutput" # flush fonction
}
# $1=liste fichier(s) à grepper, [$2]: N &| nofile &| novide &| ligneVide &| date &| commentXY &| sources
# si aucun fichier dans la liste retour: 'nofile|vide|inexistant'
# /!\ protéger les chemins avec " (surtout si plusieurs chemins ou joker)
# option largeur, 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', OPTION FINALE! commentaire supplémentaire à filtrer, ex: comment//
# option 'sources' affiche les sources en "colonne" (3 premières col: largeur maxi)
# ex. cumul option: "10 novide nofile lignevide" (espace obligatoire, pas d'autre séparateur)
# cmd de base: grep -Ersv '^#|^$' file|dossier "options"
f_grep_file(){ # 12/12/2017
local file content display='' motif col1=0 col2=0 col3=0 col4=0 un deux trois quatre
# motif de base "^[[:blank:]]*#|^[[:blank:]]*$"
motif="^[[:blank:]]*#"
[[ ! "$2" =~ lignevide ]] && motif+="|^[[:blank:]]*$"
[[ "$2" =~ comment ]] && comment=${2##*comment} # on garde les symboles de commentaires à la fin
[[ "$2" =~ comment ]] && motif+="|^[[:blank:]]*$comment"
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, gawk
largeur=${2%% *}
content=$(gawk -v larg="$largeur" '
!/^[[:blank:]]*$/ { printf "%-"larg"s",$1; $1=""; printf "%s\n",$0 } # exclut ligne vide
' <<< "$content")
fi
if [[ "$2" =~ sources ]]; then
content=$(
while read -r un deux trois quatre; 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 ))
done <<< "$content"
while read -r un deux trois quatre; do
[ "$un" ] && printf "%-"$col1"s %-"$col2"s %-"$col3"s %-"$col4"s \n" "$un" "$deux" "$trois" "$quatre"
done <<< "$content"
)
fi
[ -d "$file" ] && file+='/' # si répertoire, ajout / final, joli
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:]]}
[ "$display" ] || display="nofile" # si display vide, inscription 'nofile'
echo -en "$display"
}
f_help(){ # 22/11/2017
local toDisplay ligne
toDisplay=(
"$GREEN ./getInfo$BLUE : exécution normale, rapport markdown de la configuration"
"$GREEN getInfo$BLUE : script installé dans le système"
""
"$STD$BOLD options:$STD$BLUE"
" -c : (catégorie) menu sélection catégorie d'analyse"
" -cs : catégorie système -cs : catégorie configuration"
" -cr : catégorie réseau -ca : catégorie analyse"
" -h : (help) affichage aide"
" -j : (journaux) analyse démarrage système, log Xorg, kernel et système, catégorie -ca"
" -l : (list) afficher le rapport markdown existant"
" -p : (paste) exporte le rapport markdown existant, durée standard du paste 7 jours"
""
" --ip : affiche ip publique (ipv4/ipv6), pas de rapport markdown"
" --mac : affiche les adresses Mac, pas de rapport markdown"
" pas de rapport markdown, $RED ROOT$BLUE requis:"
" --serial : affiche n° série disques, batterie et châssis"
" --ssid : affiche configurations ssid, infos confidentielles,$RED NetworkManager$BLUE requis"
""
" -tn : durée du paste de n jour(s)"
" -us : upgrade spécial du script (pas de mise à jour automatique, maj du script en place)"
""
" -i, --install : installation du script dans le système, root requis"
" -r, --remove : suppression du script dans le système, root requis"
" -u, --upgrade : upgrade script installé si maj possible"
" -v, --version : version du script, en ligne et en cours d'exécution"
)
for ligne in "${toDisplay[@]}"; do
echo -e "$ligne"
done
echo -e "$STD\n plus d'infos: $GREEN$url_notice\n$STD"
}
# $1=texte à épurer
f_lifting(){ # 16/12/2017
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"
}
# 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
# $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(){ # 15/12/2017
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" >> "$fileOutput"
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 gawk
# 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(){ # 12/12/2017
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
[ "$2" == "marge" ] && margin=" "
display=$(cat $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
IFS=$'\n' # normalement inutile
while read -r ligne; do
ligne=${ligne//\\/\\\\} # re echappement des antislash, utile pour efiboot, méthode bourrin, sans comprendre le pourquoi
# # 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"
IFS="$IFS_INI"
echo -e "$display2"
}
# $1=modules [$2=repertoire spécifique de recherche], affiche emplacements et modules trouvés
f_search_ko(){ # 13/12/2017
local dir="/lib/modules/$(uname -r)" motif emplacement imod mod_ko
[ "$1" ] && motif="$1" || return 1
[ "$2" ] && dir="$2"
motif="($motif|${motif//_/-})\.ko"
emplacement=$( du -a "$dir" | grep -Ew "$motif" )
if [ "$emplacement" ]; then
IFS=$'\n'
for imod in $emplacement; do
imod=${imod#*$dir}
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(){ # 18/12/2017
local cardsAudio cmd_cards version_alsa card_alsa cmd_card_alsa cmt_card_alsa pluriel text
local mod_alsa cmd_mod_alsa cmt_mod_alsa modAudio cmd_modAudio cmt_modAudio
local alert_alsa
x_audio=1
fe_nb_audio=0
# devices
fe_cards_audio=$( figet_lspci "audio" "name" )
fe_cards_audio=$( f_lifting "$fe_cards_audio" )
fe_cards_audio=${fe_cards_audio% controller}
fe_cards_audio=${fe_cards_audio% Controller}
fe_cards_audio=${fe_cards_audio#*: }
fe_nb_audio=$(f__wcv -l "$fe_cards_audio")
[ "$1" == "silent" ] && return 0 # pas d"affichage
[ "$fe_nb_audio" -eq 0 ] && return 0
###
# lspci
cardsAudio=$( figet_lspci "audio" "raw" )
cmd_cards="lspci -nnv | grep -EiA6 '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=$( gawk '{
sub(/Advanced Linux Sound Architecture Driver /,"")
sub(/Version /,"")
sub(/.$/,"")
print $0
}' /proc/asound/version )
card_alsa=$( gawk ' { print " "$0 }' /proc/asound/cards )
[ "$( grep -c '\[.*\]' <<< "$card_alsa" )" -gt 1 ] && pluriel="s" || unset pluriel
cmd_card_alsa="cat /proc/asound/cards"
cmt_card_alsa="carte"$pluriel" enregistée"$pluriel""
# modules alsa
mod_alsa=$( gawk '{ print $2 }' /proc/asound/modules )
mod_alsa=$( sort <<< $mod_alsa )
[ "$( f__wcv -l "$mod_alsa" )" -gt 1 ] && pluriel="s" || unset pluriel
cmd_mod_alsa="cat /proc/asound/modules"
cmt_mod_alsa="module"$pluriel" alsa"
# modules kernel
figet_lspci "audio" "module" &>/dev/null # obtention module utilisé
modAudio="$fg_modules_lp"
cmd_modAudio="lsmod | grep -Ew '$fg_srch_mod_lp'"
[ "$( f__wcv -wv "$modAudio" "^[[:alnum:]]" )" -gt 1 ] && pluriel="s" || unset pluriel
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 "$mod_alsa" "$cmd_card_alsa" "$cmt_card_alsa"
f_dspl cmd "$modAudio" "$cmd_modAudio" "$cmt_modAudio"
}
fi_batt(){ # 14/12/2017
local pluriel
(( x_batt == 1 )) || figet_batt
[ "$fg_batt" ] || return 0 # pas de batterie
[ "$fg_nb_batt" -gt 1 ] && pluriel="s" || unset pluriel
###
f_prnt tit2 "batterie"$pluriel
f_dspl sans "$fg_batt"
}
# [$1=silent], assigne $fe_nb_bluez, $fe_cards_bluez
fi_bluez(){ # 18/12/2017
local bluez cmd_bluez cmt_bluez mod cmd_mod cmt_mod pluriel text
x_bluez=1
fe_nb_bluez=0
if hcitool scan &>/dev/null && [[ $( f__which hciconfig ) ]]; then
fe_nb_bluez=$( hciconfig name 2>/dev/null )
fe_cards_bluez=$( grep -Eo '^hci[0-9]+' <<< $fe_nb_bluez )
fe_nb_bluez=$( grep -c '^hci[0-9].*$' <<< $fe_nb_bluez )
fe_cards_bluez=${fe_cards_bluez//[[:cntrl:]]/ } # mise en liste inline
else
fe_nb_bluez=0
fi
[[ "$1" == "silent" || "$fe_nb_bluez" -eq 0 ]] && return 0
###
# état
bluez=$( hciconfig -a )
[ "$( grep -c '^hci[0-9]' <<< "$bluez" )" -gt 1 ] && pluriel="s" || unset pluriel
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'"
[ "$( f__wcv -l "$mod" )" -gt 1 ] && pluriel="s" || unset pluriel
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(){ # 13/12/2017
local confs toScrut=(
'/etc/default/grub'
# '/boot/grub/grub.cfg' # pour info
# '/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
'/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" )
###
f_prnt tit2 "fichiers configuration divers"
f_dspl cmd "$confs" "grep -Ersv '^#|^$' <fichiers désirés>"
}
fi_cpu(){ # 14/12/2017
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 # appel 'base' des tags, obtention $CPU_FLAGS
cpu_flags=$( sed -n 's/^flags.*: \(.*\)$/\1/p;' /proc/cpuinfo | sed -n '1p'| \
tr ' ' '\n' | sort | tr '\n' ' ' | xargs )
for iflag in $cpu_flags; do
text_flags+="$(
gawk -v motif="$iflag" -F '⟷' '
BEGIN { IGNORECASE=1; pattern = "^"motif"[[:blank:]]" }
$0 ~ pattern { $1 = motif; exit }
END { if( $1 != motif ) {$1 = motif; $2 = "?"}
printf ("%-20s %s",$1,$2 ) #ligne
}' <<< $CPU_FLAGS
)"$'\n'
done
text_flags=${text_flags%[[:cntrl:]]} # suppression \n final
[ "$cpu_flags" ] && 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
[ "$(( ${fg_cpu:0:1} ))" -gt 1 ] && pluriel="s" || unset pluriel
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
}
fi_disk(){ # 14/12/2017
local cmd_dd_temp="" dd_temp="" exclude_df liste_df disk_df disk_df_i cmd_dfi cmd_dfh disk_lsblk fstab
local resume idResume idSwap idisk text pluriel
local alert_dd_temp alert_file_resume alert_uuidResume
(( x_disk == 1 )) || figet_disk
# hddtemp
if [ $( f__which hddtemp ) ]; 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=${dd_temp::-1} # 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
# exclude_df="exclude-type=aufs --exclude-type=devfs --exclude=devtmpfs --exclude-type=fdescfs
# --exclude-type=iso9660 --exclude-type=linprocfs --exclude-type=procfs --exclude-type=squashfs
# --exclude-type=sysfs --exclude-type=tmpfs --exclude-type=unionfs"
# disk_df=$( df -h --output=source,target,fstype,size,used,avail,pcent --$exclude_df )
# disk_df_i=$( df -i --$exclude_df )
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"
# 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 )
# fstab
fstab=$( f_grep_file "/etc/fstab" "notitre" )
# resume
resume=$( f_grep_file "/etc/initramfs-tools/conf.d/resume" "notitre" )
if [ "$resume" == "nofile" ]; then
# alert resume absent
alert_file_resume="Pas de fichier _resume_ dans /etc/initramfs-tools/conf.d/ \n"
alert_file_resume+="Ce n'est pas forcément une erreur, la plus grosse partition swap devrait être "
alert_file_resume+="choisie dans ce cas. \n"
alert_file_resume+="À investiguer si erreur au boot ou boot très long ou erreur update-initramfs. \n"
alert_file_resume+="Notes: <https://kyodev.frama.io/kyopages/debian/petits-soucis/#fichier-resume> \n"
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_, voir supprimer ce fichier"
fi
[ "$fg_nb_disk" -gt 1 ] && pluriel="s" || unset pluriel
###
f_prnt tit2 "disque"$pluriel
# espace des partitions fixes montées
f_prnt 1 "$(gawk -F ': ' '{print $1": **"$2"**"}' <<< $fg_disk_part_fix_tot)"
f_prnt
f_prnt code
# disques fixes et amovibles
[ "$(wc -w <<< $fg_disk_fixe)" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l "$(printf '%-17s: %s' "disque$pluriel fixe$pluriel" "$fg_disk_fixe")"
[ "$(wc -w <<< $fg_disk_amov)" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l "$(printf '%-17s: %s' "disque$pluriel amovible$pluriel" "$fg_disk_amov")"
f_prnt
# partitions fixes montées / swap / non montées
[ "$(wc -w <<< $fg_disk_part_fixe_m)" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l "$(printf '%-24s: %s' "partition$pluriel fixe$pluriel montée$pluriel" "$fg_disk_part_fixe_m")"
[ "$(wc -w <<< $fg_disk_part_swap)" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l "$(printf '%-24s: %s' "partition$pluriel swap$pluriel" "$fg_disk_part_swap")"
[ "$(wc -w <<< $fg_disk_part_fixe_nm)" -gt 1 ] && pluriel="s" || unset pluriel
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
[ "$(wc -w <<< $fg_disk_part_amov_m)" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l "$(printf '%-32s: %s' "partition$pluriel amovible$pluriel montée$pluriel" "$fg_disk_part_amov_m")"
[ "$(wc -w <<< $fg_disk_part_amov_nm)" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l "$(printf '%-32s: %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
[ "$fg_nb_disk" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt 1 "**types de disque"$pluriel"** "
f_prnt
f_prnt l1 "| sata | usb | mmc | nvme |"
f_prnt l1 "| :---: | :---: | :---: | :---: |"
f_prnt l1 "| $fg_disk_ata | $fg_disk_usb | $fg_disk_mmc | $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
f_dspl cmd "$fstab" "grep -Ev '^#|^$' /etc/fstab" "fstab"
# 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"
}
fi_dmesg(){ # 2/12/2017
local dmesg_err dmesg_warn dmesg_crit file info_ucode alert_firmBug text nb_lignes=25
local alert_firmBug
file="/tmp/$$-$RANDOM-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" >> "$fileOutput"
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=$( cat $file-ucode )
[ "$info_ucode" ] && info_ucode="microcode processeur mis à jour au boot"
alert_firmBug=$( cat $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(){ # 6/12/2017
local efiboot text
[ $( f__which efibootmgr ) ] || return 0 # pas d'efi
efiboot=$( gawk '
/^Boot0/ { gsub(/\\/,"\\\\",$3); printf "%s %s: \n %s \n", $1, $2, $3 };
! /^Boot0/ { print $0 }
' <<< $( efibootmgr -v 2>/dev/null ) )
###
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
fi_gpu(){ # 18/12/2017
local cards cmd_cards prefixCmd openGl pluriel text
local stck_glxinfo glx_dvc cmd_glx_dvc stck_glxinfoOpt stck_glxinfoDri glx_dvc_temp
local cmd_openGl 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
local toScrut confs ifile fileConfs cmd_confs cmt_confs
x_gpu=1
fe_nb_gpu=0
# liste/description gpu et qte
fe_gpu=$( figet_lspci "video" "name")
fe_gpu=${fe_gpu/VGA compatible controller: }
fe_gpu=${fe_gpu/Display controller: }
fe_gpu=${fe_gpu/3D controller: }
fe_nb_gpu=$( f__wcv "-l" "$fe_gpu" )
# version Xorg Server
fe_Xorg=$( xdpyinfoT -display $DISPLAY 2>/dev/null | grep 'version:' ) # version Xorg
fe_Xorg=${fe_Xorg//*version: /X.Org X Server}
[ "$fe_Xorg" ] || fe_Xorg=$( X -version 2>/dev/null ) # si ver Xorg vide, essai X
[ "$fe_Xorg" ] || fe_Xorg=$( Xorg -version 2>/dev/null ) # si ver Xorg vide, essai Xorg
if [ "$wayland" ]; then
xScreens=$( xrandr --verbose 2>/dev/null | grep -A1 'Screen' )
[ "$( grep 'XWAYLAND' <<< $xScreens )" ] && wayland+=" Xwayland"
[ "$( grep 'XWAYLAND' <<< $xScreens )" ] && fe_Xorg+=" {Xwayland}"
fi
[ "$1" == "silent" ] && return 0
[ "$fe_nb_gpu" -eq 0 ] && return 0 # pas de gpu, rien à voir
### ## xorgOnly
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 "
done
cmd_confs="grep -Ersv '^#|^$' $fileConfs"
[ "$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_log_xorg "notitre"
return 0
fi
###
# lspci
# lspci -nnk | grep -EiA 3 'vga|display|3d'
# lspci -nnv | grep -iEA10 'vga|display|3d'
# lspci -nnv -s $( lspci | grep -Ei 'vga|display|3d' | cut -d" " -f1 )
# lspci -nnv -s $(gawk '/VGA |Display |3D / {print $1}' <<< $( lspci ) )
cmd_cards="lspci -nnv -s $(gawk '/VGA |Display |3D / {print $1}' <<< $( lspci ))"
if [ "$fe_nb_gpu" -eq 1 ]; then # une seule carte
cards=$( figet_lspci "video" "raw" )
else # plusieurs cartes, essai optirun ou prime
cards=$( figet_lspci "video" "raw" "graph")
prefixCmd=$(basename $(which toto) 2>/dev/null) || prefixCmd="DRI_PRIME=1"
cmd_cards="$prefixCmd $cmd_cards"
fi
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"
alert_hybrid+="Voir DRI_PRIME, vga-switcheroo, Bumbledee...?"
fi
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
# openGl / glxinfo
if [ $( f__which glxinfo ) ]; 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 [ $( f__which optirun ) ]; 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 [ $( f__which optirun ) ]; then
fi_gpu_openGl "opt" # ajout à $openGl existant, pas de redondance
cmd_openGl="optirun glxinfo"
else # DRI
fi_gpu_openGl "dri" # redondance
cmd_openGl="DRI_PRIME=1 glxinfo"
fi
else
cmd_openGl="glxinfo | grep -E "
cmd_openGl+="'OpenGL vendor|OpenGL renderer|OpenGL version|shading language|OpenGL extensions'"
fi
openGl=${openGl// string:/:} # suppression chaîne ' string'
openGl=${openGl% } # suppression espace final éventuel
fi
# xrandr: résolutionS & providers & preferred/current
if [ $( f__which xrandr ) ]; then
resolutions="$( xrandr --query | grep -A11 'Screen [0-9]' )"
cmd_resolutions="xrandr --query | grep -A11 'Screen [0-9]'"
cmt_resolutions="10 premières résolutions possibles"
providers="$( xrandr --listproviders )" # DRI: ok, sort 2 fournisseurs
cmd_providers="xrandr --listproviders"
current_preferred="$( xrandr --verbose | 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
figet_lspci "video" "module" &>/dev/null # obtention module utilisé
modGpu="$fg_modules_lp"
cmd_modGpu="lsmod | grep -Ew '$fg_srch_mod_lp'"
[ "$( f__wcv -wv "$modGpu" "^[[:alnum:]]" )" -gt 1 ] && pluriel="s" || unset pluriel
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**"
[ "$( f__wcv "-wv" "$fg_resolution" "pixels" )" -gt 1 ] && pluriel="s" || unset pluriel
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(){ # 28/11/2017
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}
[ $( f__which uniq ) ] && openGl=$( uniq <<< $dri_glxinfo ) || 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
}
# $1=-4|-6|-46 protocole
fi_ip_pub(){ #v 14/12/2017
local itest option="$1"
option=${option//46/4 6}
for itest in $option; do
itest=-${itest//-}
if figet_ip_pub "$itest" ; then
echo "$BOLD$fg_ip_pub$STD"
else
echo "pas de connectivité ipv${itest#-}"
fi
done
}
fi_journal(){ # 18/12/2017
local jctl_boot jctl_alert_k jctl_crit_k jctl_err_k jctl_warn_k jctl_warn_nok jctl_last jctl_size file
local info_ucode text nb_lignes=25
local alert_jctl_persist alert_firmBug
if [ -z $( f__which journalctl ) ]; then
fi_dmesg # pas systemd, appel dmesg
return 0
fi
file="/tmp/$$-$RANDOM-journalctl"
[ "$EUID" -eq 0 ] || echo
f__sudo " LC_ALL=C journalctl --no-hostname --boot -1 &>$file-persistant ; \
LC_ALL=C journalctl --no-pager --no-hostname -b0 -k -p 1 > $file-alert ; \
LC_ALL=C journalctl --no-pager --no-hostname -b0 -k -p 2..2 > $file-crit ; \
LC_ALL=C journalctl --no-pager --no-hostname -b0 -p 3..3 > $file-err ; \
LC_ALL=C journalctl --no-pager --no-hostname -b0 -p 4..4 > $file-warn ; \
LC_ALL=C journalctl --no-pager --no-hostname -b0 -p 4 -n$nb_lignes > $file-last ; \
LC_ALL=C journalctl --disk-usage > $file-size ; \
LC_ALL=C journalctl --no-pager --no-hostname -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" >> "$fileOutput"
return 0
fi
# début des logs, extraction à partir de file-last (toujours lignes) pour début des logs
jctl_boot=$( gawk -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 --no-hostname --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 --no-hostname -b0 -k -p1" \
"**kernel emergency 0 & alerte 1**, $nb_lignes premières lignes"
f_dspl cmd "$jctl_crit_k" "journalctl --no-hostname -b 0 -k -p 2..2" \
"**kernel critique**, $nb_lignes premières lignes"
f_dspl cmd "$jctl_err_k" "journalctl --no-hostname -b0 -k -p 3..3" \
"**kernel erreur**, $nb_lignes premières lignes)"
f_dspl cmd "$jctl_warn_k" "journalctl --no-hostname -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 --no-hostname -b0 -p 1 | grep -v kernel" \
"**hors kernel, emergency 0 & alerte 1**, $nb_lignes premières lignes"
f_dspl cmd "$jctl_crit_nok" "journalctl --no-hostname -b0 -p 2..2 | grep -v kernel" \
"**hors kernel, critique**, $nb_lignes premières lignes"
f_dspl cmd "$jctl_err_nok" "journalctl --no-hostname -b0 -p 3..3 | grep -v kernel" \
"**hors kernel, erreur**, $nb_lignes premières lignes"
f_dspl cmd "$jctl_warn_nok" "journalctl --no-hostname -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 --no-hostname -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"
}
fi_locale(){ # 10/12/2017
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")
[ $( f__which localectl ) ] && localeCtl=$( localectl --no-pager status )
locale=$( locale )
# timezone
timezone="$(f_grep_file "/etc/timezone*")"
if [ $( f__which timedatectl ) ]; 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 # évite erreur $DISPLAY en root wayland
xKeyboardMap="n/a en root sous wayland"
else
[ $( f__which setxkbmap ) ] && xKeyboardMap="$(setxkbmap -query)"
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"
}
# [$1=notitre]
fi_log_xorg(){ # 18/12/2017
local toScrut xfile xfileTest="" logXorg cmd_logXorg="" cmt_logXorg extract dateFile text nb_lignes=50
local info_logs
[[ "$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>"
info_logs="voir les options appliquées par défaut: **cat $cmd_logXorg | grep '(\\\*\\\*)**' "
cmd_logXorg="grep -Es '\(WW\)|\(EE\)|\(\?\?\)' $cmd_logXorg"
cmt_logXorg="Xorg.log"
###
f_prnt tit2 "journaux Xorg" "[ \"$1\" != \"notitre\" ]"
f_dspl cmd "$logXorg" "$cmd_logXorg" "$cmt_logXorg"
f_dspl_alrt "$info_logs" "info"
}
fi_mem(){ # 5/12/2017
local memoire swappiness 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 )
###
f_prnt tit2 "mémoire"
f_dspl cmd "$memoire" "free -h"
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(){ # 18/12/2017 ( matériel )
local cards cmd_cards modEth cmd_modEth cmt_modEth modWln cmd_modWln cmt_modWln pluriel text
local alert_wlx
x_net=1
fe_nb_reseau=0
# devices
fe_cards_reseau=$( figet_lspci "net" "name" ) # noms des cartes réseau détectées, mix ethernet/wifi
fe_cards_reseau=${fe_cards_reseau/Network controller: /Network :}
fe_cards_reseau=${fe_cards_reseau/Ethernet controller: /Ethernet:}
fe_cards_reseau=${fe_cards_reseau/Wireless Network/Wireless}
fe_nb_reseau=$(f__wcv -l "$fe_cards_reseau") # 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
cards=$( figet_lspci "net" "raw" )
cmd_cards="lspci -nnv | grep -EiA 15 'network|ethernet'"
# 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 )
#modules ethernet
figet_lspci "ethernet" "module" &>/dev/null # obtention module utilisé
modEth="$fg_modules_lp"
cmd_modEth="lsmod | grep -Ew '$fg_srch_mod_lp'"
[ "$( f__wcv -wv "$modEth" "^[[:alnum:]]" )" -gt 1 ] && pluriel="s" || unset pluriel
cmt_modEth="**Ethernet:** $( f__wcv -wv "$modEth" "^[[:alnum:]]" ) module"$pluriel" utilisé"$pluriel
# modules wifi
figet_lspci "wireless" "module" &>/dev/null # obtention module utilisé
modWln="$fg_modules_lp"
cmd_modWln="lsmod | grep -Ew '$fg_srch_mod_lp'"
[ "$( f__wcv -wv "$modWln" "^[[:alnum:]]" )" -gt 1 ] && pluriel="s" || unset pluriel
cmt_modWln="**Wifi:** $( f__wcv -wv "$modWln" "^[[:alnum:]]" ) module"$pluriel" utilisé"$pluriel
(( x_ip == 1 )) || 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(){ # 5/12/2017
[ $( f__which nmcli ) ] || return 0
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
local nm_connected text
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
nm_connected=$( LC_ALL=C nmcli -f SSID,ACTIVE,IN-USE device wifi list | gawk '/yes[[:space:]]+\*/ {print $1}' )
###
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(){ #v2 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
}
fi_pkg_apt(){ #v3 12/12/2017
local dateMaj nb_packages ifile info_update text pluriel
local sources cmt_sources cmd_sources dir_source result
local apt_v apt_version apt_prefs cmt_apt_prefs cmd_apt_prefs
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 size_clean size_cleanH
local clean qte_clean cmt_clean cmd_clean size_clean
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 metaPkg cmd_metaPkg cmt_metaPkg 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" sources )
cmt_sources="dépôts"
cmd_sources="grep -Ersv '^#|^$' /etc/apt/sources.list /etc/apt/sources.list.d/*.list"
# sources non .list
shopt -s extglob # activer opérateurs de correspondance étendue
dir_source="/etc/apt/sources.list.d"
if result=$( f__dir "-l" "$dir_source" "\.list" ) ; then
alert_non_list="ignoré, extension non valable dans "$dir_source":\n"
alert_non_list+="${result//$dir_source\/}"
alert_non_list="${alert_non_list//$'\n'/ }"
fi
shopt -u extglob # désactiver opérateurs de correspondance étendue
# apt prefs
apt_prefs=$( f_grep_file "/etc/apt/preferences.d/*" )
cmd_apt_prefs="grep -Erv '^#|^$' /etc/apt/preferences.d/"
cmt_apt_prefs="préférences apt"
if [ "$1" == "confOnly" ]; then
local apt_unUpgrd cmd_unUpgrd cmd_apt_history essai
# shopt -s extglob
# 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 "
info_update+="pas trop ancienne, la précision de cette partie du rapport pourra en être améliorée."
# divers
dateMaj=$( date -r /var/cache/apt/pkgcache.bin '+%d/%m/%Y %H:%M %z' 2>/dev/null) || \
dateMaj=$( date -r /var/cache/apt '+%d/%m/%Y %H:%M %z' 2>/dev/null ) # /var/lib/dpkg/
nb_packages=$( dpkg -l | grep -c '^ii' )
#nb_packages alternatif: grep -c '\.list' <<< $(ls -1 /var/lib/dpkg/info/*.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=$( gawk '{if ( $1 > 1.5 ) {print "https inutile"}}' <<< $apt_v )
if f__requis "apt-transport-https" "debOnly" && [ "$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=$( gawk '{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=($( gawk '/ newly installed/{print $1" "$10}' <<< $stck_upgd )) # tableau
[ "${qte_upgradable[0]}" ] || qte_upgradable=("-1" "-1") # si erreur
# upgrade
[ "$(( "${qte_upgradable[0]}" ))" -gt 1 ] && pluriel="s" || unset pluriel
cmt_upgrade="${qte_upgradable[0]} paquet"$pluriel" à mettre à jour"
[ "${qte_upgradable[0]}" -eq 0 ] && cmt_upgrade=${cmt_upgrade/0 /aucun }
cmd_upgrade="apt list --upgradable"
if [ "${qte_upgradable[0]}" -gt 0 ]; then
upgrade=$( grep '^Inst' <<< "$stck_upgd" | sort | gawk '{
sub(/\(/,"",$4); sub(/\/.*/,"",$5); sub(/\[/,"",$3); sub(/\]/,"",$3);
printf "%-25s source: %-25s %-20s ⇉ %-20s\n",$2,$5,$3,$4 }')
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, commencer par vérifier avec **apt update** (en root)"
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
[ "$(( "${qte_upgradable[1]}" ))" -gt 1 ] && pluriel="s" || unset pluriel
cmt_notUpgraded="${qte_upgradable[1]} paquet"$pluriel" nécessitant une mise à jour profonde)"
alert_full_upgrade="ces paquets peuvent être mis à jour avec avec: **apt full-upgrade**"
fi
echo -n "◇"
# autoremove
toRemove=$( LC_ALL=C apt-get autoremove --simulate | grep -E 'Remv | newly installed' )
toRemove=$( sort <<< $toRemove )
qte_toRemove=$( gawk '/ newly installed/{ printf $6 }' <<< $toRemove )
toRemove=$( sed '/newly/d' <<< "$toRemove" ) # suppression ligne état
[ "$(( "$qte_toRemove" ))" -gt 1 ] && pluriel="s" || unset pluriel
cmt_toRemove="$qte_toRemove paquet"$pluriel" inutile"$pluriel
[ "$qte_toRemove" -eq 0 ] && cmt_toRemove=${cmt_toRemove/0 /aucun }
cmd_toRemove="apt autoremove --simulate"
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\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=$( grep '^Del' <<< $( LC_ALL=C apt-get autoclean --simulate 2>/dev/null ) )
qte_autoclean=$( f__wcv -l "$autoclean" )
[ "$qte_autoclean" -gt 1 ] && pluriel="s" || unset pluriel
cmt_autoclean="$qte_autoclean archive"$pluriel" périmée"$pluriel
[ "$qte_autoclean" -eq 0 ] && cmt_autoclean=${cmt_autoclean/0 /aucune }
cmd_autoclean="apt autoclean --simulate"
if [ "$qte_autoclean" -gt 0 ]; then
autoclean=$( gawk '{print $2}' <<< $autoclean | sort | tr '\n' ' ' )
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 LC_ALL=C du -chS /var/cache/apt/archives/ 2>/dev/null )
size_clean=$( du -ckS /var/cache/apt/archives/ 2>/dev/null | grep -i 'total' ) # affichage en ko
size_clean=${size_clean%[[:blank:]]total}
size_cleanH=$( du -chS /var/cache/apt/archives/ 2>/dev/null | grep -i 'total' ) # affichage en human
size_cleanH=${size_cleanH%[[:blank:]]total}
qte_clean=$( f__dir -c /var/cache/apt/archives "lock|partial" )
[ "$qte_clean" -gt 1 ] && pluriel="s" || unset pluriel
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 | gawk '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" )
[ "$qte_non_ii" -gt 1 ] && pluriel="s" || unset pluriel
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 | gawk '! /^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 [ $( f__which deborphan ) ]; then
deborphan=$( deborphan -P )
cmd_deborphan="deborphan -P"
qte_deborphan=$( f__wcv "-l" "$deborphan" )
[ "$qte_deborphan" -gt 1 ] && pluriel="s" || unset pluriel
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
holded=$( apt-mark showhold )
qte_holded=$( f__wcv "-l" "$holded" )
[ "$holded" ] && holded=$( sort <<< $holded | tr '\n' ' ' )
[ "$qte_holded" -gt 1 ] && pluriel="s" || unset pluriel
cmt_holded="$qte_holded paquet"$pluriel" figé"$pluriel
[ "$qte_holded" -eq 0 ] && cmt_holded=${cmt_holded/0 /aucun }
cmd_holded="apt-mark showhold"
# kernel
# metaPkg=$( dpkg -l | grep -i -E 'linux-(image|headers)-([0-9]{3}|amd)' )
metaPkg=$( gawk '
BEGIN{IGNORECASE=1}
/linux-(image|headers)-([0-9]{3}|amd)/ { printf "%-3s %-30s %s ",$1, $2, $3
$1=$2=$3=$4=""; print $0
}' <<< $( dpkg -l ) )
cmd_metaPkg="dpkg -l | grep -i -E 'linux-(image|headers)-([0-9]{3}|amd)'"
cmt_metaPkg="métapaquet noyau"
# kernel=$( dpkg -l | grep -i -E "linux-(headers|image)-$(uname -r)" )
kernel=$( gawk '
BEGIN{IGNORECASE=1}
/linux-(headers|image)-'$(uname -r)'/ { printf "%-3s %-30s %s ",$1, $2, $3
$1=$2=$3=$4=""; print $0
}' <<< $( dpkg -l ) )
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_prnt
f_dspl_alrt "$info_update" "info"
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 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"
if [ $( f__which deborphan ) ]; then
f_dspl cmd "$deborphan" "$cmd_deborphan" "$cmt_deborphan"
f_dspl_alrt "$alert_deborphan" "info"
fi
f_dspl cmd:vide "$holded" "$cmd_holded" "$cmt_holded"
f_dspl cmd "$metaPkg" "$cmd_metaPkg" "$cmt_metaPkg"
f_dspl cmd "$kernel" "$cmd_kernel" "$cmt_kernel"
}
fi_pkg_x(){ #v2 1/12/2017
local nb_packages cmd_nbPackages sources cmd_sources holded cmd_holded
if [[ ${1%:*} == "dnf" ]]; then # Fedora, RedHat (rpm)
# http://dnf.readthedocs.io/en/latest/command_ref.html
# http://landoflinux.com/linux_dnf_command_examples.html
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="wc -l <<< \$(ls -1 /var/log/packages)"
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="wc -l <<< \$(ls -1 /var/lib/eopkg/package)"
elif [[ ${1#*:} == "Guix" ]]; then # Gnu Guix
nb_packages=$( f__dir -c "/gnu/store/*/" )
cmd_nbPackages="wc -l <<< \$(ls -1 /gnu/store/*/)"
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="wc -l <<< \$(ls -1 /nix/store/*/)"
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(){ # 15/12/2017 ( configuration )
local ip_a interfaces route resolv iwconfig canal_wifi netmgr imgr netmgrinst netmgrrun text pluriel
local ipa slaac='' slaac_mac='' ip4 gw4 ip4_p ip6 gw6 adr_temp slaac slaac_mac
local alert_ifconfig alert_slaac
# 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' <<< $ip_a )
route=$( sort <<< $( ip -4 route show ) )$'\n\n'
route+=$( ip -6 route show )
# 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)
if [ $( f__which iwconfig ) ]; then #paquet wireless-tools requis
iwconfig=$( LC_ALL=C iwconfig 2>/dev/null )
fi
# iwlist (/sbin)
if [ $( f__which iwlist ) ]; then # canal wifi utilisé; /sbin, paquet wireless-tools requis
canal_wifi=$( LC_ALL=C iwlist chan 2>/dev/null | grep 'Current Frequency' | grep -Eio 'channel [0-9]+' )
fi
# manager réseaux
declare -A netmgr=(
["NetworkManager"]="/usr/sbin/NetworkManager"
["Wicd"]="/usr/sbin/wicd"
["ConnMan"]="/usr/sbin/connmand"
)
for imgr in ${!netmgr[*]}; do
if [ -e "${netmgr[$imgr]}" ]; then
netmgrinst+="$imgr "
fi
if [ $( ps -ef | grep -c ${netmgr[$imgr]} ) -ge 2 ]; then
netmgrrun+=$( ps -ef | grep -om1 "${netmgr[$imgr]}"".*$" )$'\n'
fi
done
netmgrinst=${netmgrinst% } # suppression dernier espace
netmgrrun=${netmgrrun%[[:cntrl:]]} # suppression dernier $'\n'
# alertes
if [ $( f__which ifconfig ) ] ; 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
figet_ip "-4"
ip4="$fg_ip"
gw4="$fg_gws"
ip4_p="$fg_ifn_prior"
figet_ip "-6"
ip6="$fg_ip"
gw6="$fg_gws"
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
[ "$( f__wcv -l "$slaac" )" -gt 1 ] && pluriel="s" || unset pluriel
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"
f_prnt
[ "$(f__wcv "-l" "$fg_gws")" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l2 "passerelle"$pluriel": ${gw4//$'\n'/ ⊗ }"
f_prnt
figet_ip "-6"
f_prnt l1 "ipv6"
f_prnt l2 "$ip6"
f_prnt
f_prnt l2 "passerelles: ${gw6//$'\n'/ ⊗ }"
f_prnt
[ "$(f__wcv "-w" "$fg_ifn_prior")" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l2 "interface"$pluriel" sortante"$pluriel" ipv6: $fg_ifn_prior" '[ "$fg_ifn_prior" ]'
[ "$(f__wcv "-w" "$ip4_p")" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l2 "interface"$pluriel" sortante"$pluriel" 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
# ip a & route & interface & resolv
f_dspl cmd "$ip_a" "ip address"
f_dspl cmd "$route" "ip route show"
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\`"
f_prnt
# network manager
f_prnt 1 "gestionnaire de réseau" '[ "$netmgrinst" ]'
[ "$(wc -w <<< $netmgrinst)" -gt 1 ] && pluriel="s" || unset pluriel
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(){ #v9 1/12/2017
local chassis_serial machineId text
(( x_disk == 1 )) || figet_disk
(( x_bat == 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(){ #v2 24/12/2017
local nm_ssid text
local fileOutput="/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
[ $( f__which nmcli ) ] || f__error "NetworkManager requis"
# connexion wifi?
/sbin/iwconfig 2>/dev/null | grep -iq ssid || f__error "pas de connexion en 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 "$fileOutput" "marge"
rm "$fileOutput"
}
fi_system(){ # 14/12/2017
local mbr uname bootImage initDaemon date_install lastboot uptime uptimePure loadAverage pluriel text
local enum_batt serverX
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 )) || figet_screen
(( x_shell == 1 )) || figet_shell
(( x_touchpad == 1 )) || fi_touchpad "silent"
(( x_wm == 1 )) || figet_wm
echo -n "ø"
# divers système
if [ -d /sys/firmware/efi ]; then
mbr="EFI"
else
mbr="Legacy (mbr)"
fi
uname=$( uname -rmo )
bootImage=$( gawk '{print $1}{i=2; while (i <= NF) { print " ",$i; i++}}' /proc/cmdline )
initDaemon=$( ps -p1 | gawk 'FNR==2 {print $4}' ) #? ps -ax | gawk '$1==1' ou ps -p1 | gawk '$1==1'
if [[ "$initDaemon" == "systemd" && $( f__which systemd ) ]]; then
initDaemon=$( systemd --version )
initDaemon=${initDaemon%%[[:space:]]\+*}
initDaemon=${initDaemon/systemd /systemd v}
fi
initDaemon=${initDaemon^}
while read -r; do
date_install=$REPLY
done <<< $( ls -lt --time-style '+FORMAT %d/%m/%Y' / )
[[ "$date_install" =~ .*([0-9]{2}/[0-9]{2}/[0-9]{4}).* ]] && date_install=${BASH_REMATCH[1]}
# lastboot="$(last -n 1 --time-format iso reboot | gawk '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=$(
gawk -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
}
}' <<< $( LC_ALL=C uptime ) )
loadAverage=$(
gawk -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)"
}' <<< $( LC_ALL=C uptime )
)
# server X
serverX="${XDG_SESSION_TYPE^}" # retourne wayland normalement si c'est le cas
serverX+=" $fe_Xorg"
[[ "$serverX" == " " && "$ENV_DISPLAY" ]] && serverX+=":no DISPLAY"
[[ "$serverX" == " " && "$ENV_SSH" ]] && serverX+=":ssh"
[ "$serverX" == " " ] && serverX="n/a"
# alimentation
if [ $( grep -c 'AC' <<< $( f__dir -lc "/sys/class/power_supply/" ) ) -gt 0 ]; then
alim_total=$( grep -cs 1 /sys/class/power_supply/AC*/online )
alimentation=$( gawk -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)
###
[ "$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 "date d'installation: $date_install"
f_prnt l2 "démon d'initialisation: $initDaemon"
f_prnt l2 "shell actif: $fg_shell"
[ "$( f__wcv -w "$fg_shells" )" -gt 1 ] && pluriel="s" || unset pluriel
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: $serverX"
f_prnt l2 "nombre d'écrans: $fg_nb_screen"
[ "$(f__wcv "-wv" "$fg_resolution" "pixels")" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l2 "résolution"$pluriel": $fg_resolution"
[ "$(wc -w <<< $fg_dm)" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l2 "display manager"$pluriel": $fg_dm"
f_prnt l2 "display manager actif: $fg_dm_actif" '[ "$fg_dm_actif" != "$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
f_prnt l1 "Matériel"
[ "$fg_nb_cpu" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l2 "$fg_nb_cpu processeur"$pluriel" $fg_cpu_arch"
[ "$fe_nb_bluez" -gt 1 ] && pluriel="s" || unset pluriel
f_prnt l2 "$fe_nb_bluez carte"$pluriel" bluetooth ($fe_cards_bluez)" '[ "$fe_nb_bluez" -gt 0 ]'
f_prnt l2 "$alimentation" '[ "$alimentation" ]'
[ "$fg_nb_batt" -gt "1" ] && pluriel="s" || unset pluriel
f_prnt l2 "$fg_nb_batt batterie"$pluriel" présente"$pluriel":" '[ "$fg_batt" ]'
f_prnt l3 "$enum_batt" '[ "$fg_batt" ]'
[ "$fe_nb_touchpad" -gt "1" ] && pluriel="s" || unset pluriel
f_prnt l2 "$fe_nb_touchpad pavé"$pluriel" tactile"$pluriel": $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**"
[ "$fg_nb_threads" -gt "1" ] && pluriel="s" || unset pluriel
f_prnt 1 "$loadAverage"
f_prnt flush
}
fi_system_analyse(){ #v 2/12/2017
[ $( f__which systemd ) ] || 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=$( systemctl --state=active,failed | grep -cE 'error|not-found|failed' )
srvcFail=$( LC_ALL=C systemctl --state=active,failed | gawk '
/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 )
[ "$qte_srvcFail" -gt 1 ] && pluriel="s" || unset pluriel
cmt_srvcFail="service"$pluriel" en erreur"
if [ "$qte_srvcFail" -gt 0 ]; then
alert_srvcFail="service"$pluriel" en erreur, statut: \n\n"
srvcFail_list=$( gawk '{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
touch "$file" 2>/dev/null
[ -w "$file" ] || file="/tmp/getInfo-graph-$RANDOM.svg"
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"
}
# [$1=silent], assigne $fe_touchpad, fe_nb_touchpad
fi_touchpad(){ # 18/12/2017
local device cmd_device toScrut xfile file_logs type type_pt pilote cmd_pilote cmt_pilote info_driver
x_touchpad=1
fe_nb_touchpad=0
device=$( grep -Ei -B1 -A8 'synaptics|alps|etps|elan' /proc/bus/input/devices ) || return 0
fe_touchpad=$( grep -i 'Name=' <<< $device )
fe_touchpad=${fe_touchpad#*Name=\"} # suppression début
fe_touchpad=${fe_touchpad%\"} # suppression fin
cmd_device="grep -Ei -B1 -A8 '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éterminer si 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=$( grep -ci 'touchpad' <<< "$fe_touchpad" )
[[ "$1" == "silent" ]] && return 0
###
if [ "$ENV_DEBIAN" ]; then
pilote=$( gawk '
/^ii/ { printf "%-30s", $2; $1=$2=$3=$4=""; print $0 }
' <<< $( dpkg -l | grep -E 'synaptics|libinput' ) 2>/dev/null)
# ' <<< $( dpkg -l *synaptics *libinput ) 2>/dev/null)
cmd_pilote="dpkg -l *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 1 "$( sed -E 's/(.*)/**\1** /' <<< $fe_touchpad )" # mise en gras
f_prnt
f_prnt tit2 "Touchpad"
f_dspl cmd "$device" "$cmd_device"
f_dspl cmd "$pilote" "$cmd_pilote" "$cmt_pilote"
f_dspl_alrt "$info_driver" "info"
}
fi_usb(){ # 17/12/2017
local lsusb size lsusb_t ls lst ils motif result ls_p bus device id periph
x_usb=1
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=$( gawk '
{
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=$( gawk '
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"
f_prnt flush
}
fi_vrms(){ # 1/12/2017
local vrms non_free contrib total text pluriel tempo
[ $( f__which vrms ) ] || 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
[ "$non_free" -gt 1 ] && pluriel="s" || unset pluriel
vrms=$( sed -E "s/Non-free packages installed on.*/$non_free paquet$pluriel non libre$pluriel installé$pluriel:/
" <<< "$vrms" )
[ "$contrib" -gt 1 ] && pluriel="s" || unset pluriel
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(){ #v2 15/12/2017
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 . ) # pas de messages, pb gentoo, pk?
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=$( gawk -F '=' '/POWER_SUPPLY_CHARGE_FULL_DESIGN=/ {printf "%d", $2/1000}' <<< $uevent ) # mA
batt_capa_full=$( gawk -F '=' '/POWER_SUPPLY_CHARGE_FULL=/ {printf "%d", $2/1000}' <<< $uevent ) # mA
batt_capa_now=$( gawk -F '=' '/POWER_SUPPLY_CHARGE_NOW=/ {printf "%d", $2/1000}' <<< $uevent ) # mA
batt_conso=$( gawk -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=$( gawk -F '=' '/POWER_SUPPLY_ENERGY_FULL_DESIGN=/ {printf "%.2f", $2/1000000}' <<< $uevent ) # W
batt_capa_full=$( gawk -F '=' '/POWER_SUPPLY_ENERGY_FULL=/ {printf "%.2f", $2/1000000}' <<< $uevent ) # W
batt_capa_now=$( gawk -F '=' '/POWER_SUPPLY_ENERGY_NOW=/ {printf "%.2f", $2/1000000}' <<< $uevent ) # W
batt_conso=$( gawk -F '=' '/POWER_SUPPLY_POWER_NOW=/ {printf "%.2f", $2/1000000}' <<< $uevent ) # W
fi
# extractions simples
batt_volt_min=$( gawk -F '=' '/POWER_SUPPLY_VOLTAGE_MIN_DESIGN=/ {printf "%.2f", $2/1000000}' <<< $uevent ) # V
batt_volt_now=$( gawk -F '=' '/POWER_SUPPLY_VOLTAGE_NOW=/ {printf "%.2f", $2/1000000}' <<< $uevent ) # V
batt_status=$( gawk -F '=' '/POWER_SUPPLY_STATUS=/ {print $2}' <<< $uevent )
batt_cycle=$( gawk -F '=' '/POWER_SUPPLY_CYCLE_COUNT=/ {print $2}' <<< $uevent )
fg_batt_serial=$( gawk -F '=' '/POWER_SUPPLY_SERIAL_NUMBER=/ {sub(/^ | $|0/,"",$2); print $2}' <<< $uevent )
alert_batt_alarm=$( cat $ibat/alarm 2>/dev/null )
[ "$alert_batt_alarm" == "0" ] && unset alert_batt_alarm || alert_batt_alarm="$ibat: $alert_batt_alarm"
# calculs
batt_sante=$( gawk '$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=$( gawk '$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=$( gawk '$1+$2+$3 != "" && $3 != 0 {print ($1-$2)/$3}' <<< "$batt_capa_full $batt_capa_now $batt_conso" )
fi
batt_restant+=$( gawk '$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 [ "$(gawk '{printf "%d", $1}' <<< $batt_sante)" -lt 50 ] && [[ "$batt_status" == "Full" || "$batt_status" == "Unknown" ]]; then
batt_detail+="batterie très mal chargée (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_uarch, $fg_vendor=AMD|Intel, $fg_nb_cpu
figet_cpu(){ #v 18/12/2017
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=$( gawk -F ':' '
/cpu MHz/ { printf "%.2f", $2/1000;exit }' <<< "$cpuinfo" )
speedMax=$( gawk '
{ printf "%.2f", $1/1000000 }' /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq 2>/dev/null )
speedMin=$( gawk '
{printf "%.2f", $1/1000000}' /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq 2>/dev/null )
speedCpu=""
if [ "$speedMin" ]; then
speedCpu+="$speedMin/"
descrCpu+="fréq. min/"
fi
if [ "$speedNom" ]; then
speedCpu+="$speedNom"
descrCpu+="nom"
fi
if [[ "$speedMax" && "$speedMax" != "$speedNom" ]]; then
speedCpu+="/$speedMax"
descrCpu+="/max"
fi
[ "$speedCpu" ] && speedCpu=$(printf "%sGHz" $speedCpu)
[ "$speedCpu" ] || speedCpu=$(gawk -F '@' '/model name/ {sub(/^ | $/,"",$2); print $2;exit}' <<< "$cpuinfo")
# motifs?: Processor Dual-Core Quad-Core Six-Core Eight-Core Core 'with Radeon * Graphics'
# nb proc
fg_nb_cpu=$(
gawk -F ':|@' '
/^physical id/ { if ($2+1 != nbCpu) nbCpu=$2+1 }
END { printf "%d",nbCpu }
' <<< "$cpuinfo" )
# traitement fg_cpu
cpu1=$(
gawk -v "speedCpu=$speedCpu" -F ':|@' '
/^model name/ {
gsub(/^ | $|\(R\)|\(TM\)|\(r\)|\(tm\)|CPU| width/,"",$2); gsub(/ /," ",$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" }
/microcode/ { sub(/^ /,"",$2); microCode=$2 }
END {
printf nbCpu" x "cpu " (" procCore "core" pllc ", " procThread "thread" pllt;
print ") {" speedCpu "} microcode:" microCode
}' <<< "$cpuinfo "
)
cpu2=$(
gawk -v "descrCpu=$descrCpu" -F ':' '
/^vendor_id/{gsub(/ /,"");gsub(/AuthenticAMD/,"AMD");gsub(/GenuineIntel/,"Intel");vendor=$2}
/^cpu family/{family=$2}
/^model[^ ]/{model=$2}; /^stepping/{rev=$2}
END {
code=sprintf("{0x%.2X|0x%.2X}",family,model);
print "{" descrCpu "}, " vendor" famille" family", modèle"model,code", révision" rev
}' <<< "$cpuinfo"
)
cpu3=$(
gawk -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=$( echo -e "${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, assigna $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(){ # 14/11/2017
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(){ #v 14/12/2017 # thanks neofetch
local de="n/a"
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-} # supression de X- (X-Cinnamon)
if [ -z "$de" ]; then
de="$DESKTOP_SESSION"
de=${DESKTOP_SESSION##*/} # suppression plus grande chaine au début jusqu'à /
fi
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 | gawk 'BEGIN{IGNORECASE = 1};/KDE_SESSION_VERSION|^_MUFFIN/' )
fi
# Format strings
if [[ "${de,,}" =~ kde ]]; then # test sur minuscules
de="$de$KDE_SESSION_VERSION"
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
fi
fg_de=${de,,} # minuscule
fg_de=${fg_de^} # caractère 1 en majuscule
###
# panel
fg_de_panel=$( gawk ' BEGIN { IGNORECASE=1 }
#inclus lxpanel, mate-panel, gnome-panel, xfceX-panel
/(gnome-shell|kicker|plasma-desktop|plasma-netbook|lxpanel|panel)$/ { print $NF; exit }
' <<< $( ps -A ) )
}
# $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_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
figet_disk(){ #v2 18/12/2017
local size type list_id idisk lsblk vendor model rev serial
unset fg_disk_fixe fg_disk_amov
x_disk=1
fg_nb_disk=0
# bug printf: caractères accentués diminuent 1 caractère sur arguments suivants, ajouter autant d'espaces
fg_disk_table="$(printf '%-5s %-8s %-6s %-10s %-18s %-6s' "disk" "taille" "type" "vendeur" "modèle" " rév.")"$'\n'
fg_disk_serial="$(printf '%-5s %-10s %-18s %-6s %-24s %s' "disk" "vendeur" "modèle " " rév." " n° série")"$'\n'
for idisk in $(f__dir -l "/sys/block/" "loop" ); do
size=$( lsblk -no SIZE -d /dev/$idisk | xargs ) #149,1G
type=$( sed -n '2p' <<< $(lsblk -no HOTPLUG /dev/$idisk) | xargs ) # 0 \n 0 \n ...
[ "$type" == "0" ] && type="Fixe" || type="Amov"
vendor=$( lsblk -no VENDOR /dev/$idisk | xargs )
model=$( lsblk -no MODEL /dev/$idisk | xargs )
serial=$( lsblk -no SERIAL /dev/$idisk | xargs )
if [[ -z "$vendor" || -z "$model" ]]; then # tentative extraction valeur via /dev/disk/by-id/
vendor="n/a"
vendor=$( ls -l /dev/disk/by-id/ | gawk ' !/-part/ && !/wwn-/ {print $9,$11}' | xargs )
vendor=$( sed -E 's/.*-(.*)_[0-9]+.*$/\1/;s/_/ /g' <<< $vendor )
fg_disk_table+=$( printf '%-5s %-8s %-6s %s' "$idisk" "$size" "$type" "$vendor" )$'\n'
fg_disk_serial+=$( printf '%-5s %s %s' "$idisk" "$vendor" "$serial" )$'\n'
else
rev=$( lsblk -no REV /dev/$idisk | xargs )
fg_disk_table+=$( printf '%-5s %-8s %-6s %-10s %-18s %-6s' "$idisk" "$size" "$type" "$vendor" "$model" "$rev")$'\n'
fg_disk_serial+=$( printf '%-5s %-10s %-18s %-6s %-24s %s' "$idisk" "$vendor" "$model" "$rev" "$serial")$'\n'
fi
# liste disques fixes ou amovibles
if [ "$( lsblk -no HOTPLUG /dev/$idisk | xargs | cut -d' ' -f2 )" == "0" ]; then
fg_disk_fixe+="$idisk " # "sda sdb ..."
else
fg_disk_amov+="$idisk "
fi
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), peut servir d'indicateur fonction déja appelée
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=$( echo "$lsblk" | gawk '/\// {print $1}' | tr '\n' ' ')
fg_disk_part_fixe_nm=$( echo "$lsblk" | gawk '!/\// && /[0-9]+/ && !/\[SWAP\]/{print $1}' | tr '\n' ' ' )
# 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=$( echo "$lsblk" | gawk '/\// {print $1}' | tr '\n' ' ' )
fg_disk_part_amov_nm=$( echo "$lsblk" | gawk '!/\// && /[0-9]+/ && !/\[SWAP\]/{print $1}' | tr '\n' ' ' )
# partitions swap
fg_disk_part_swap=$( echo "$(lsblk -no KNAME,MOUNTPOINT)" | gawk '/\[SWAP\]/ {print $1}' | tr '\n' ' ' )
[ "$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 | xargs)"
fg_disk_part_fix_tot="$(sed 's/G/Go/g; s/M/Mo/g; s/K/ko/g' <<< $fg_disk_part_fix_tot)"
[ "$fg_disk_part_fix_tot" ] || fg_disk_part_fix_tot="n/a"
# liste des disques par type
list_id=$( ls -l /dev/disk/by-id/ | gawk '{print $9,$11}' )
fg_disk_ata=$( sed '/^ata/!d; /part/d' <<< $list_id | gawk -F '/' '{print $NF}' | tr '\n' ' ')
fg_disk_usb=$( sed -n '/part/d; /^usb/p' <<< $list_id | gawk -F '/' '{print $NF}' | tr '\n' ' ' )
# fg_disk_mmc=$( sed '/^mmc/!d; /part/d; /\/mmcblk/!d; s/^.*\(mmcblk..*\)$/\1/' <<< $list_id | tr '\n' ' ' )
fg_disk_mmc=$( sed '/^mmc/!d; /part/d' <<< $list_id | gawk -F '/' '{print $NF}' | tr '\n' ' ' )
fg_disk_nvme=$( sed '/^nvme/!d; /part/d' <<< $list_id | gawk -F '/' '{print $NF}' | tr '\n' ' ' )
[ "$fg_disk_ata" ] || fg_disk_ata="-" && fg_disk_ata=$( tr ' ' '\n' <<< "$fg_disk_ata" | sort | tr '\n' ' ' )
[ "$fg_disk_usb" ] || fg_disk_usb="-" && fg_disk_usb=$( tr ' ' '\n' <<< "$fg_disk_usb" | sort | tr '\n' ' ' )
[ "$fg_disk_mmc" ] || fg_disk_mmc="-" && fg_disk_mmc=$( tr ' ' '\n' <<< "$fg_disk_mmc" | sort | tr '\n' ' ' )
[ "$fg_disk_nvme" ] || fg_disk_nvme="-" && fg_disk_nvme=$( tr ' ' '\n' <<< "$fg_disk_nvme" | sort | tr '\n' ' ' )
}
# assigne $fg_distrib
figet_distrib(){ #v 14/12/2017
local prefix version
x_distrib=1
# priorité /etc/os-release, version officielle systemd
[ -e "/etc/os-release" ] && source "/etc/os-release" || source "/usr/lib/os-release"
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
[[ $( grep -is 'microsoft' /proc/version ) ]] && fg_distrib=$( lsb_release -sd 2>/dev/null )"/windows"
[[ $( grep -is 'chrome-' /proc/version ) || -f "/dev/cros_ec" ]] && fg_distrib=$( lsb_release -sd 2>/dev/null )"/chrome-os"
fi
[ "$fg_distrib" ] || fg_distrib=$( lsb_release -sd 2>/dev/null )
# prefix sur nom fichier éventuels *[_-][version|release]
[ "$prefix" ] || prefix=$( f__dir -l '/etc/*_version' | sed -En 's#/etc/(.*)_version#\1#p' )
[ "$prefix" ] || prefix=$( f__dir -l '/etc/*-version' | sed -En 's#/etc/(.*)-version#\1#p' )
[ "$prefix" ] || prefix=$( f__dir -l '/etc/*-release' "os" | sed -En 's#/etc/(.*)-release#\1#p' )
# spécial complément
[ "$prefix" == "redstar" ] && prefix="Red Star OS"
[ "$prefix" ] && 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
[ "$fg_distrib" ] || fg_distrib="${OS^} (indéterminé)"
}
# display manager, assigne $fg_dm (liste) ou 'n/a', $fg_dm_actif
figet_dm(){ #v1 18/12/2017
local dm_list="cdm entranced gdm3 gdm qingy kdm ldm lightdm lxdm mdm nodm orthos sddm slim wdm xdm"
local idm ps systemctl x11
x_dm=1
fg_dm=""
ps=$(ps -ef) # plus joli pour cmde manuelle ps=$(ps -auxf)
ps=${ps,,} # tout en minuscules
for idm in $dm_list; do
if grep -iq "bin/$idm$" <<< "$ps"; then
# if [ "${ps/*"$idm"*/test}" == "test" ]; then # pb: doublon gdm/gdm3 fun & speed? grepless (remplacement $idm et alentours, si idm présent, valeur test)
fg_dm+="${idm^} "
fg_dm_actif="${idm^}"
elif [[ -e /var/run/$idm".pid" || -e /var/run/$idm".pid" || -e /run/$idm || -e /run/$idm || -d /run/$idm/ || -d /var/run/$idm/ ]]; then
fg_dm+="${idm^} "
fg_dm_actif="${idm^}"
fi
done
fg_dm=${fg_dm% } # supression espace final
if [[ -z "$fg_dm" && -e "/etc/X11/default-display-manager" ]]; then
x11=$(cat /etc/X11/default-display-manager)
fg_dm=${x11##*/} # conservation dernier champs ifs '/'
fi
if [[ -z "$fg_dm" && "${ps/*startx*/test}" == "test" ]]; then
fg_dm="(startx)"
fg_dm_actif="(startx)"
fi
fg_dm_actif=${fg_dm_actif^}
if [ -z "$fg_dm_actif" ] && type -p systemctl &>/dev/null; then
fg_dm_actif=$(grep 'Main PID' <<< $(systemctl status display-manager))
fg_dm_actif=${fg_dm_actif##* } # conservation dernier champs ifs ' '
fg_dm_actif=${fg_dm_actif/\(/} # suppression (
fg_dm_actif=${fg_dm_actif/\)/} # suppression )
[ ${fg_dm// } ] || fg_dm="$fg_dm_actif"
fi
[ "$fg_dm" ] || fg_dm="n/a"
[ "$fg_dm_actif" ] || fg_dm_actif="n/a"
}
# informations DMI (firmware partie matériel), $1=[head], assigne $fg_dmi
figet_dmi(){ #v2 16/12/2017
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
# 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
if [ "$1" == "head" ]; then
[ "$product" ] && fg_dmi=$(printf "%-5s : %s " "prod." "$product")$'\n'
[[ "$board" && "$indic1" != "$indic2" ]] && fg_dmi+=$(printf "%-5s : %s " "board" "$board")$'\n'
[ "$bios" ] && fg_dmi+=$(printf "%-5s : %s " "bios" "$bios")
fi
[ "$product" ] && fg_dmi="$product "$'\n'
[[ "$board" && "$indic1" != "$indic2" ]] && fg_dmi+="$board "$'\n'
[ "$bios" ] && fg_dmi+="$bios "
fg_dmi=$( f_lifting "$fg_dmi" )
unset chassis_type
}
# infos température et fan via acpi, assigne $fg_hw
figet_hw(){ #v2 14/12/2017
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
unset fan temp
for ihw in /sys/class/hwmon/*; do
[ -e $ihw/name ] && name=$( cat $ihw/name 2>/dev/null ) || name="indéfini"
## TEMPÉRATURE
if grep -Eq 'temp[0-9]+' <<< $( f__dir -l $ihw ) ; then # tempX dans un nom de fichier
# extraction label
labelT=$( printf "%s/" "$( cat $ihw/temp*_label 2>/dev/null)" | tr ' ' '.' | tr '\n' ' ' )
# extraction températures
inputT=$( gawk '$0!="" && $0!=0 {printf "%.1f/", $1/1000}' $ihw/temp*_input 2>/dev/null )
critT=$( gawk '$0!="" && $0!=0 {printf "%.1f/", $1/1000}' $ihw/temp*_crit 2>/dev/null )
hystT=$( gawk '$0!="" && $0!=0 {printf "%.1f/", $1/1000}' $ihw/temp*_crit_hyst 2>/dev/null )
maxiT=$( gawk '$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#/} #[ ${critT:0:1} == "/" ] && critT=${critT:1}
hystT=${hystT#/} # suppression / en début de variable
maxiT=${maxiT#/}
# suppression dernier caractère (/) fin (nécessaire si multi-valeurs)
[ "$inputT" ] && inputT=${inputT::-1}
[ "$labelT" ] && labelT=${labelT::-1}
[ "$critT" ] && critT=${critT::-1}
[ "$hystT" ] && hystT=${hystT::-1}
[ "$maxiT" ] && maxiT=${maxiT::-1}
# 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 grep -Eq 'fan[0-9]+' <<< $( f__dir -l $ihw ) ; then # fanX dans nom de fichiers
# extraction label
labelF=$( printf "%s/" $( cat $ihw/fan*_label 2>/dev/null) )
# extraction vitesse fan, \047=' pour insérer séparateur de milliers
inputF=$( gawk '$0!="" && $0!=0 {printf "%\047d/", $1}' $ihw/fan*_input 2>/dev/null )
# suppression dernier caractère (/) fin (nécessaire si multi-valeurs)
[ "$labelF" ] && labelF=${labelF::-1}
[ "$inputF" ] && inputF=${inputF::-1}
# formation affichage
if [ "$inputF" ]; then
fan+="$(printf "%-8s %st/mn %s" "$name" "$inputF" "$labelF")"$'\n'
fi
fi
done
fg_hw="$temp$fan"
[ "$fg_hw" ] && fg_hw=${fg_hw::-1}
}
# $1=-4|-6, assigne $fg_ip, $fg_gws6, $fg_ifn, $fg_mac
figet_ip(){ # 15/12/2017
local target ifn
x_ip=1
[ $( f__which ip ) ] || return 1
[ "$1" ] && proto="$1" || proto="-4"
# adresses ip
fg_ip=$(
gawk -v proto="$proto" '
BEGIN { if (proto == -6) esp=41; else esp=16 }
/scope global/ {
sub(/wl.*/,$2" (wifi)",$2); sub(/.*en.*|.*eth.*/,$2" (ethernet)",$2);
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 "%-17s: %-"esp"s (%s) %s \n",$2,$4,lft,scope }
/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 }
' <<< $( ip $proto -o address )
)
# passerelles
fg_gws=$(
gawk '
BEGIN { if (proto == -6) esp=42; else esp=12 }
/default via/ { printf "%-"esp"s (%s)\n",$3,$5 }
' <<< $( ip $proto route )
)
# interface sortante
if [ "$proto" == "-6" ]; then
target=$( gawk '/proto ra / { print $1; exit}' <<< $( ip $proto -o route ) )
fg_ifn_prior=$( ip $proto route get $target )
fg_ifn_prior=$( ip $proto route get $target | sed -En 's/.*dev (.*) proto.*src ([0-9a-f:]+).*/\1 (\2)/p' )
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(){ #v 24/12/2017
local dig_test ip_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
)
}
list_ip4_dig(){ # testé 11/12/2017
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
)
}
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
)
}
list_ip6_dig(){ # testé 11/12/2017
dig_test=(
-6/myip.opendns.com/aaaa/@resolver1.ipv6-sandbox.opendns.com
-6/myip.opendns.com/aaaa/@resolver2.ipv6-sandbox.opendns.com
)
}
x_ip_pub=1
option="$1"
unset fg_ip_pub
# assignation variables
if [ "$1" == "-4" ]; then
ping -4 -c1 conncheck.opensuse.org &>/dev/null || ping -4 -c1 free.fr &>/dev/null || return 1 # test connectivité
list_ip4_dig
list_ip4
ip_telnet=4.ifcfg.me
elif [ "$1" == "-6" ]; then
ping -6 -c1 conncheck.opensuse.org &>/dev/null || ping -6 -c1 free.fr &>/dev/null || return 1 # test connectivité
list_ip6_dig
list_ip6
ip_telnet=6.ifcfg.me
fi
# DIG
if type -p dig &>/dev/null && [ -z "$fg_ip_pub" ]; then
for iip in ${dig_test[*]}; do
fg_ip_pub=$( dig +short ${iip//\// } )
[ "$fg_ip_pub" ] && break
done
fi
# WGET
if type -p wget &>/dev/null && [ -z "$fg_ip_pub" ]; then
cmd="wget --quiet --timeout=2 --tries=1 -o /dev/null -O - "
for iip in ${ip_test[*]}; do
fg_ip_pub=$( $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 --max-time 5"
for iip in ${ip_test[*]}; do
fg_ip_pub=$( $cmd $iip )
[ "$fg_ip_pub" ] && break
done
fi
# TELNET
if type -p telnet &>/dev/null && [ -z "$fg_ip_pub" ]; then
fg_ip_pub=$( telnet $ip_telnet 23 2>/dev/null | grep "Your IPv${option/-}" )
fg_ip_pub=${fg_ip_pub##* }
fi
# NC
if type -p nc &>/dev/null && [ -z "$fg_ip_pub" ] && [ "$option" != "-6" ]; then
fg_ip_pub=$( nc $ip_telnet 23 2>/dev/null | grep "Your IPv${option/-}" )
fg_ip_pub=${fg_ip_pub##* }
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 après avoir installé dig (dnsutils) et wget"
fi
}
# $1=audio|video|net & audio|ethernet|wireless, $2 objet raw|name|module, $3=[graph] (optirun, DRI),
# affiche device (name), lspci détail (raw)
# pour module (module kernel), video|ethernet|wireless, assigne $fg_modules_lp $fg_srch_mod_lp
figet_lspci(){ # 17/12/2017
local motif slots lspci display='' prefixCmd modLspci mod_file
x_lspci=1
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
# uniquement les devices
if [ "$2" == "name" ]; then
while read -r field1 lspci; do
lspci=${lspci%(rev *)}
display+="$lspci "$'\n'
done <<< $( lspci | grep -Ei "$motif" )
display=$( f_lifting "$display" )
# lspci détaillé RAW || MODULE
elif [[ "$2" == "raw" || "$2" == "module" ]]; then
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
else
for lspci in $slots; do
if [[ "$3" == "graph" && "$( f__which optirun )" ]]; then
lspci=$( optirun lspci -nnv -s $lspci )
elif [ "$3" == "graph" ]; then
lspci=$( DRI_PRIME=1 lspci -nnv -s $lspci )
else
lspci=$( lspci -nnv -s $lspci ) # normalement inutile, le contexte DRI_PRIME pourrait marcher partout
fi
lspci=${lspci/(prog-if*])} # suppression (prog-if...])
lspci=${lspci/Capabilities: <access denied>[[:cntrl:]][[:blank:]]} # suppression Capabilities: <access denied> (user)
display+="$lspci"$'\n\n' # double \n pour espace entre card
done
fi
fi
# module kernel
if [ "$2" == "module" ]; then
fg_modules_lp=''
[ "$lspci" ] || return 1
# module utilisé
modLspci=$( gawk -F ': ' '
/Kernel modules/ {print $2}
' <<< $lspci )
modLspci=${modLspci// /|} # si jamais plusieurs modules ??..
modLspci=${modLspci%|} # si | final
modLspci=${modLspci#|} # si | au début
# modules et emplacement
fg_modules_lp=$( lsmod | grep -Ew "$modLspci" )
mod_file=$( f_search_ko "$modLspci" )
if [ "$mod_file" ]; then
fg_modules_lp="$fg_modules_lp\n\n$mod_file"
fi
fg_srch_mod_lp="$modLspci"
return
fi
display=${display%[[:cntrl:]]} # suppression \n final
echo -en "$display\n"
}
# $1=mem|swap [total|notitle|nocoltitle], assigne $fg_mem ($2=debug all cols + free)
# indépendant de procps, affichage plus clair que free, mais résultats identiques
figet_mem(){ # 14/12/2017
local freeDebug MemTotal MemFree MemAvailable Buffers Cached SReclaimable Shmem MemUsed
local SwapTotal SwapFree SwapCached col a b c MemLibre
x_mem=1
[ "$2" == "debug" ] && freeDebug="$(free -hw | sed '3d')"
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 [ "$2" == "debug" ]; then
local espace=$(printf '% 6s')
fg_mem="$espace""mém.: totale utilisée libre shared buffers cache disponible"$'\n'
fg_mem+="$espace""vive:$MemTotal$MemUsed$MemFree$Shmem$Buffers$Cached$MemAvailable"$'\n'
[ "$fg_mem" ] && fg_mem=${fg_mem::-1} # suppression dernier $'\n'
echo "$fg_mem"
echo "$freeDebug"
fi
[ "$fg_mem" ] && fg_mem=${fg_mem::-1} # suppression dernier $'\n'
}
# $1=bluetooth, assigne $fg_modules, $fg_mod_motif, fg_srch_mod
figet_modules(){ # 14/12/2017
local modules dir separator mod_ko
x_modules=1
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=$( gawk '{ 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 fg_resolution=n/a[ (ssh)] & fg_nb_screen=n/a ou valeurs
figet_screen(){ #v2 18/12/2017
x_screen=1
fg_nb_screen=0
fg_resolution="n/a"
[ "$ENV_DISPLAY" ] && fg_resolution+=":no Display"
[ "$ENV_SSH" ] && fg_resolution+=":ssh"
[ $( f__which xrandr ) ] || fg_resolution+=":xrandr absent"
[ $( f__which xdpyinfo ) ] || fg_resolution+=":xdpyinfo absent"
[[ "$wayland" && "$EUID" -eq 0 ]] && fg_resolution+=":wayland root"
[[ "$fg_resolution" =~ : ]] && return 0 # retourne n/a ... toutes les causes dans $fg_resolution
##
# xrandr & et xdpyinfo ne retourne pas de nombre écrans correct (multiplex? hybrid?)
fg_resolution=$( gawk '/[0-9]\*/ {gsub(/\*\+/,"",$2); printf "%s pixels (%dHz), ", $1, $2}' <<< $( xrandr --query ) )
fg_resolution=$( gawk '/dimensions/ { print $2, $3 ", " }' <<< $(xdpyinfo) )
fg_resolution="${fg_resolution%,*}" # suppression ',*'
[ "$(xargs <<< $fg_resolution)" ] || fg_resolution="n/a"
[[ "$fg_resolution" =~ n/a ]] || fg_nb_screen=$( grep -o 'pixels' <<< $fg_resolution | grep -c . )
}
# assigne $fg_shell, $fg_shells
figet_shell(){ #v2 14/12/2017 # thanks neofetch
local shell ish
x_shell=1
# shell en cours altern: fg_shell="$( ps -p $PPID -o comm= 2>/dev/null )"
fg_shell=${SHELL##*/} # suppression jusqu'au dernier /, pas de chemin
fg_shell=${fg_shell,,}
case ${shell:=$fg_shell} in # shell nul, donc assigné avec $fg_shell
bash )
shell=${BASH_VERSION%-*} # BASH_VERSION: 4.4.12(1)-release, suppression -* final
;;
mksh | ksh )
shell=" "$( "$SHELL" -c 'printf "%s" "$KSH_VERSION"' )
shell=${shell/ * KSH} # suppression ' * KSH'
shell=${shell/version} # suppression 'version'
;;
* )
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 # by-pass sinon soucis sous fedora et openSuse?
for ish in $( f_grep_file "/etc/shells" "notitre" ); do # élimine lignes vides et commentées
fg_shells+=${ish##*/}" " # conservation dernier "champs", ifs '/'
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(){ # 14/12/2017
local flagRep xfile xfileTest=""
x_ucode=1
(( 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 (compositor, pas en variable publique, pas fiabilisé)
figet_wm(){ #v 14/12/2017 base départ neofetch
local id wm_brut compositor
x_wm=1
fg_wm="n/a"
[ $( f__which xprop ) ] || 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 ) # = xprop -root | grep _NET_SUPPORTING_WM_CHECK
id=${id##* } # suppression plus grande chaîne au début jusqu"à ' '
# wm_brut=$( xprop -id "$id" )
wm_brut=$( xprop -id "$id" -notype -len 100 -f _NET_WM_NAME 8t ) # xprop -id "$id" -notype _NET_WM_NAME
[ "$debug" ] && echo -e "\n$( xprop -id "$id" )\n"
wm_brut=${wm_brut,,} # MINUSCULES
fg_wm=${wm_brut/*_net_wm_name = } # suppression jusqu'à 'name = '
fg_wm=${fg_wm/\"} # suppression premier"
fg_wm=${fg_wm/\"*} # suppression 2e " avec éventuels caractères suivants
# Window Maker does not set _NET_WM_NAME
[[ "$fg_wm" =~ "windowmaker" ]] && fg_wm="wmaker"
# Fallback for Wayland wms (sway)
[[ "$fg_wm" == "xwlc" ]] && fg_wm=$( ps -e | grep -m1 -Eo 'sway|orbment|velox|orbital' )
fg_wm=${fg_wm^} # caractère 1 en majuscule
# Compositor, dev en cours, essai version
if [[ "$wm_brut" =~ marco_version ]]; then # Mate, ok
compositor=${wm_brut/*_marco_version = } # suppression jusqu'à ...
compositor=${compositor/\"} # suppression premier"
compositor=${compositor/\"*} # suppression 2e " avec éventuels caractères suivants
compositor="Marco v$compositor"
fg_wm=${fg_wm/ (marco)} # suppression (marco) dans wm
fi
if [[ "$wm_brut" =~ mutter_version ]]; then
compositor=${wm_brut/*_mutter_version = } # suppression jusqu'à ...
compositor=${compositor/\"} # suppression premier"
compositor=${compositor/\"*} # suppression 2e " avec éventuels caractères suivants
compositor="Mutter v$compositor"
fi
if [[ "$wm_brut" =~ muffin_version ]]; then # cinnamon, ok
compositor=${wm_brut/*muffin_version = } # suppression jusqu'à ...
compositor=${compositor/\"} # suppression premier"
compositor=${compositor/\"*} # suppression 2e " avec éventuels caractères suivants
compositor="Muffin v$compositor"
fg_wm=${fg_wm/ (muffin)} # suppression (muffin) dans wm
fi
# Gnome2, Metacity
# XFCE, rien pour Xfwm4
# en aveugle, pour test et adaptations futures
[[ "$wm_brut" =~ compiz ]] && compositor+='compiz'
[[ "$wm_brut" =~ compton ]] && compositor+='compton'
[[ "$wm_brut" =~ dwc ]] && compositor+='dwc'
[[ "$wm_brut" =~ fireplace ]] && compositor+='fireplace'
[[ "$wm_brut" =~ gnome-shell ]] && compositor+='gnome-shell'
[[ "$wm_brut" =~ grefson ]] && compositor+='grefson'
[[ "$wm_brut" =~ kmscon ]] && compositor+='kmscon'
[[ "$wm_brut" =~ kwin ]] && compositor+='kwin'
[[ "$wm_brut" =~ moblin ]] && compositor+='moblin'
[[ "$wm_brut" =~ rustland ]] && compositor+='rustland'
[[ "$wm_brut" =~ sway ]] && compositor+='sway'
[[ "$wm_brut" =~ swc ]] && compositor+='swc'
[[ "$wm_brut" =~ wayhouse ]] && compositor+='wayhouse'
[[ "$wm_brut" =~ westford ]] && compositor+='westford'
[[ "$wm_brut" =~ weston ]] && compositor+='weston'
compositor=${compositor^} # caractère 1 en majuscule
[ "${compositor,,}" == "${fg_wm,,}" ] && unset compositor
[ "$compositor" ] && compositor="{$compositor}"
#final
fg_wm="$fg_wm $compositor"
}
# aiguillage export paste
fipaste(){ # 10/11/2017
f__requis "curl"
if [ "$?" -gt 0 ]; 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
fipaste_curl_pastery "$fileOutput" "$pasteDuration" "$optDebug"
# à tester fipaste_curl_markdownshare "$fileOutput"
}
# $1=fichier à exporter, $2 durée de conservation en jour; $3 debug
fipaste_curl_pastery(){ # 25/10/2017
[ -e "$1" ] || f__error "fichier $1 inexistant"
local curl id pluriel
# 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"
f__info "merci contacter $projet, $contact pour aider à parfaire le script"
else
id="$(echo $curl | cut -d '"' -f 4)"
[ "$(( "$pasteDuration" ))" -gt 1 ] && pluriel="s" || unset pluriel
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" >> "$fileOutput"
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
}
# inscription dans tache upgrade en anacron hebdomadaire, via cron horaire, $1=upgrade|install|remove
fscript_cronAnacron(){ # 22/12/2017
local dirAnacron dirSpool fileAnacron
[ "$( type -t fscript_cronAnacron_special )" ] && 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 "$dirSpool/$script"* &>/dev/null
rm "$fileAnacron" &>/dev/null
rmdir "$dirSpool" "$dirAnacron" &>/dev/null
;;
esac
}
# version script en ligne, [$1=update], assigne $ver_script_install, $ver_script_online, $script_aJour=ok|KO
fscript_get_version(){ # 23/12/2017
local wget_log="/tmp/wget_$RANDOM.log"
x_script_get_version=1
if [ -e "$script_install" ]; then
ver_script_install=$( grep -m1 '^version=' $script_install | cut -d'=' -f2 )
fi
[ "$ver_script_install" ] || ver_script_install="Non installé"
f__info "raw" "script en place: $GREEN$ver_script_install"
ver_script_online=$( wget -q --timeout=15 -o "$wget_log" -O - "$url_script" | grep -m1 '^version=' | cut -d'=' -f2 )
if [ "$?" -ne 0 ]; then
rm "$wget_log"
f__wget_test "$url_script"
fi
if [ "$ver_script_online" ]; then
if [ "$ver_script_install" != "$ver_script_online" ]; then
script_aJour="KO"
else
script_aJour="ok"
fi
f__info "script en ligne: $YELLOW$ver_script_online"
else
f__info "version script en ligne$RED non accessible"
fi
rm "$wget_log"
}
# installation du script dans le système, fscript_install_special possible
fscript_install(){ # 22/12/2017
if grep -q 'bin' <<< "$( dirname $0 )" ; then
f__info "$RED""l'installation dans le système doit se faire depuis un script local $GREEN(./$script -i )"
return 1
fi
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 -i"
return $?
fi
[ "$( type -t fscript_install_special )" ] && 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 "$0" &>/dev/null ## 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 ./)"
}
# suppression du script dans le système, fscript_remove_special possible
fscript_remove(){ # 22/12/2017
if ! grep -q 'bin' <<< "$( dirname $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
if [ "$EUID" -ne 0 ]; then
f__info "vous devez être$RED ROOT$BLUE pour supprimer ce script dans le système"
f__sudo "exec $0 -r"
return $?
fi
[ "$( type -t fscript_remove_special )" ] && fscript_remove_special # test, si fonction spécifique, appel
# suppression de /opt lien /usr/bin
rm "$script_install" &>/dev/null
unlink "/usr/bin/$script" &>/dev/null
# cron/anacron remove
fscript_cronAnacron "remove"
f__info "log" "$script $version supprimé du système."
}
# mise à jour script
fscript_update(){ # 23/12/2017
local dirTemp="/tmp/$script-maj" wget_log="/tmp/wget_$RANDOM.log"
[ "$(type -t fscript_update_special)" ] && fscript_update_special # test, si fonction spécifique, appel
if [ -z "$updateSpecial" ] && ! grep -q 'bin' <<< "$( dirname $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_aJour" == "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"
wget -q --tries=2 --timeout=15 -o "$wget_log" -O "$dirTemp/$script" "$url_script"
if [ "$?" -ne 0 ]; then
rm -rf "$dirTemp/"
rm -f "$wget_log"
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 "$updateSpecial" ] && fscript_cronAnacron "upgrade"
f__info "log" "$script mis à jour en version $ver_script_online $updateSpecial"
else
f_info "log" "$script: échec update" "mauvais téléchargement, réessayer plus tard"
fi
rm -rf "$dirTemp/"
rm -f "$wget_log"
}
prg_init(){ # 4/12/2017
PATH='/usr/sbin:/usr/bin:/sbin:/bin'
TERM=xterm
IFS_INI="$IFS"
IFS=$' \t\n'
export PATH TERM IFS
# 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+="/"
# aucune erreur visible, prévoir option --debug
# exec 2>/dev/null
# exec 2>"$script.log" # à tester
# test bash v4
[ "$BASH_VERSINFO" == 4 ] || f__error "bash v4 requis" "version installée: $BASH_VERSION"
# 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
[ "$(ps -ef | grep -c 'wayland')" -gt 1 ] && wayland="wayland"
[ "$WAYLAND_DISPLAY" ] && wayland="wayland"
# test SSH
[[ "$SSH_CLIENT" || "$SSH_CLIENT" || "$SSH_CLIENT" ]] && ENV_SSH="ssh"
# test $DISPLAY
[ -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
[ "$EUID" -eq 0 ] && fu_user="root" || f__error "user détecté, mais pas de home: /home/$fu_user"
f__info "user root"
fi
# requis pour fonctionnement programme
f__requis "gawk wget ip>iproute2 lspci>pciutils wc>coreutils uptime>procps" || exit 1
# detect rapide systeme deb
[ $( f__which dpkg ) ] && ENV_DEBIAN="oui"
# définition couleurs
f__color
}
prg_1(){ # début 2/12/2017
echo > "$fileOutput"
chown $fu_user: "$fileOutput" &>/dev/null
chmod 666 "$fileOutput" &>/dev/null # rw-rw-rw-, si root permet écriture & effacement à tous
echo -e "* **$script** sur *$(uname -n)* \n" > "$fileOutput"
echo -e "$ligneRapport \n" >> "$fileOutput"
echo -e "--- \n" >> "$fileOutput"
}
prg_2(){ # traitements principaux 1/12/2017
if [[ "$1" == all || "$1" =~ s ]]; then #systeme, matériel -cs
echo -e "# ▷ Système" >> "$fileOutput"
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 "•"
$i
done
fi
if [[ "$1" == all || "$1" =~ c ]]; then #configuration #debian, packages -cc fi_conf
echo -e "# ▷ Configuration" >> "$fileOutput"
for i in fi_efi fi_locale fi_conf fi_vrms fi_packagers ; do
echo -n "•"
$i
done
fi
if [[ "$1" == all || "$1" =~ r ]]; then #reseau -cr
echo -e "# ▷ Réseau" >> "$fileOutput"
for i in fi_reseau fi_nm ; do
echo -n "•"
$i
done
fi
if [[ "$1" == all || "$1" =~ a ]]; then #analyse -ca
echo -e "# ▷ Analyse" >> "$fileOutput"
for i in fi_system_analyse fi_log_xorg fi_journal ; do
echo -n "•"
$i
done
fi
[[ "$1" == all ]] || f_prnt_md "$fileOutput"
}
prg_3(){ # fin de traitements
echo -e "--- \n" >> "$fileOutput"
echo -e "$ligneRapport \n" >> "$fileOutput"
f__dialog_oui_non "non" "\n exporter sur le pastebin par défaut?" && fipaste
f__info "le rapport est disponible en local, fichier:$YELLOW $fileOutput" \
"vous pouvez le visualiser ultérieurement avec $GREEN$script -l" \
"vous pourrez aussi l'exporter avec $BLUE$script -p"
}
prg_menu(){ # 12/12/2017
function display_menu {
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"
display_menu "$GREEN$script -c$RED""s$STD : catégorie système" \
"$GREEN$script -c$RED""c$STD : catégorie configuration"
display_menu "$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
[ "$REPLY" ] && REPLY="-c${REPLY,,}" || REPLY="all"
REPLY=$( sed 's/-call/all/' <<< $REPLY )
exec $0 "$REPLY"
}
######## début script / initialisation
# tests au démarrage
prg_init
# logo et définition couleurs
f_affichage
options=$@
# traitement option paramètres
for j in $options; do
case $j in
--debug-paste )
optDebug="debugPaste"
;; # si debug, retour json de pastery.net
-t* )
pasteDuration="$(sed -En 's/-t([0-9]+)/\1/p' <<< $j)"
;; # durée de conservation standard du paste en jours
esac
done
options="$(sed -E 's/--debug-paste//g; s/-t[0-9]+//g' <<< $options | xargs)" # nettoyage options
[ "$options" ] || options="all"
# paramètres généraux
[ "$pasteDuration" ] || pasteDuration=7 # durée de conservation standard du paste en jours
fileDev="/opt/bin/fileDev"
fileOutput="getInfo_rapport.md"
script_install="/opt/bin/$script"
script_logs="/var/log/sdeb_$script.log"
url_script="https://frama.link/getInfo"
url_notice="https://frama.link/doc-getInfo"
# test si frama.link ok, sinon fallback sur framagit
if [[ "$options" =~ all|-d|-h|-c|-v ]]; then
if ! f__wget_test "$url_script" "test"; then
url_script="https://framagit.org/kyodev/kyopages/raw/master/scripts/$script"
url_notice="https://kyodev.frama.io/kyopages/scripts/getInfo/"
fi
fi
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)"
# traitement options menu catégories
for k in $options; do
categorie+="$(sed -En 's/-c([a-z]+)/\1/p' <<< $k)"
options="$(sed -E 's/-c[a-z]+//' <<< $k | xargs)"
done
[ "$categorie" ] && options+=" -c$categorie"
# actions
for j in $options; do
case $j in
-t | --test )
ORIGIN='test'
prg_1 "$*"
echo -n "•"
fi_log_xorg
echo; f_prnt_md "$fileOutput"
exit ;; # test
-c* | all )
[ "$j" == "-c" ] && exec $0 "menu"
prg_1 "$*"
j=$(sed -E 's/-c//' <<< $j)
prg_2 "$j"
prg_3
exit ;; # rapport complet ou par catégorie
-dx )
prg_1 "$*"
fi_gpu "xorgOnly"
f_prnt_md "$fileOutput"
exit ;; # essai détail, xorgOnly
-dp )
prg_1 "$*"
fi_pkg_apt "confOnly"
f_prnt_md "$fileOutput"
exit ;; # essai util source/apt confOnly
-j )
prg_1 "$*"
prg_2 "a"
exit ;; # exporte le rapport existant
-l )
f_prnt_md "$fileOutput"
exit ;; # afficher le rapport existant
-p )
fipaste
exit ;; # exporte le rapport existant
-h )
f_help
exit ;; # affichage help
--ip )
fi_ip_pub "-46"
echo
exit ;; # affiche ip public
--mac )
figet_ip
f__info "adresses MAC:\n$STD$BOLD$fg_mac"
exit ;; # affiche adresses mac
--serial )
fi_serial
exit ;; # affiche n° série
--ssid )
fi_ssid
exit ;; # affiche configurations ssid, root requis
-i | --install )
fscript_install
exit ;; # installation du script dans le système
-r | --remove )
fscript_remove
exit ;; # suppression du script dans le système
-u | --upgrade )
opType="upgrade" # log si f__error
fscript_update
exit ;; # upgrade script si maj possible
-us )
opType="upgrade" # log si f__error
updateSpecial="update spécial actif"
script_install="$(dirname $0)/$script"
fscript_update
exit ;; # upgrade spécial
-v | --version )
fscript_get_version
exit ;; # version du script, en ligne et exécuté
menu | * )
prg_1 "$*"
prg_menu
exit ;; # affichage help
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