kyopages/scripts/getInfo

3717 lines
158 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=2.47.0
date="27/11/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
#####
# assigne $affichage_text
f__affichage(){ # 29/10/2017
f__color
affichage_text=" _ ___ __
__ _ ___| |_|_ _|_ __ / _| ___
/ _' |/ _ \ __|| || '_ \| |_ / _ \
| (_| | __/ |_ | || | | | _| (_) |
\__, |\___|\__|___|_| |_|_| \___/
|___/ "
clear
echo -e "$BLUE$affichage_text\n$YELLOW version $version - $date$STD\n"
}
# detect system architecture, assign $architecture : 32bits, i686 | 64bits, amd64 (x86_64),
# return 1 on unknown architecture
# remarque, debian: dpkg --print-architecture affiche i386
f__architecture(){ # 26/11/2017 spécifique
case "$(uname -m)" in
amd64 | x86_64 )
architecture="64bits, amd64 (x86_64)";;
i?86 | x86 )
architecture="32bits, i686";;
* )
case "$(getconf LONG_BIT)" in
64 )
architecture="64bits, amd64 (x86_64)";;
32 )
architecture="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(){ # 08/10/2017
local reply param
[[ "$1" =~ -t[0-9]{1,2} ]] && param="$(sed -En 's/.*(-t[0-9]{1,2}).*/\1/p' <<< $1)"
printf "$BLUE$2$STD"
[[ "$1" =~ oui ]] && printf " [O/n] " || printf " [o/N] "
if [ "$param" ]; then
read -t2 reply
else
read reply
fi
if [ -z "$reply" ]; then
[[ "$1" =~ oui ]] && reply="oui" || reply="non"
fi
echo
if [[ ${reply,,} =~ ^ou?i?$ ]]; then return 0; else return 1; fi
}
# affichage $1 en rouge, $1++ optionnels en bleu, sortie script sur erreur, log $1 si $opType=upgrade
f__error(){ # 15/10/2017
echo -e "\n$RED $script $version, erreur critique: $1 $STD"
for (( i=2 ; i<=$# ; i++ )); do
echo -e " $BLUE${!i}$STD"
done
echo
if [ "$opType" == "upgrade" ]; then f__log "$script $version: $1"; fi
exit 1
}
# conversion human, source ko, $1=nombre à convertir, affiche ko ou Mo ou Go, ! dépendance gawk
f__unit_human(){ # 09/10/2017
printf "$( 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 )"
}
# affichage des paramètres en bleu, si $1=raw pas de ligne vide à la fin, si $1=log alors uniquement $2 logué
f__info(){ # 15/10/2017
local depart=1 i
if [ "$1" == "raw" ] || [ "$1" == "log" ]; then depart=2; fi
[ "$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é à 10000octets, $1 message à loguer
f__log(){ # 27/10/2017
if [ -w "$fileLogs" ]; then
if [ "$(stat -c %s $fileLogs)" -ge "10000" ]; then
echo "$(date +%Y%m%d\ %H%M%S) $1" &>/dev/null > "$fileLogs"
else
echo "$(date +%Y%m%d\ %H%M%S) $1" &>/dev/null >> "$fileLogs"
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(){ # 22/11/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 [ $( f__which dpkg ) ]; then # package only et debian
LC_ALL=C dpkg --get-selections | grep -qE "^$package[[:space:]]+install" \
&& debOnlyPresent+="$package " || debOnlyAbsent+="$package "
fi
elif [ -z $( f__which $command ) ]; 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=rep à scanner [$2=profondeur max|4 défaut] [$3=profondeur encours|0 défaut]
# affichage stdout si $fileOutput non définis, /usr/bin/strings (binutils) requis
f__scandir(){ # 10/11/2017
[ -d "$1" ] || f__error "erreur sur le répertoire à scanner"
f__requis "strings>binutils" || exit 1
local repToScan irep rc text prof prof_max tempo
[ "${1: -1}" == "/" ] && repToScan="$1" || repToScan="$1/" # ajout / final si besoin
[ "$2" ] && prof_max="$2" || prof_max=4 # profondeur max par défaut si besoin
[ "$3" ] && prof=$3 || prof=0 # initialisation compteur profondeur en cours si nécessaire (début)
text="répertoire: $repToScan \n"
for irep in $(ls $repToScan); do # contenu du répertoire
prof=$(( $prof+1 )) # niveau++
if [ -d "$repToScan$irep" ]; then # si c'est un répertoire
# si compteur niveau <= max, scandir, sinon suivant dans la boucle
[ "$prof" -le "$prof_max" ] && f__scandir "$repToScan$irep/" "$prof_max" "$prof" || continue
else # si c'est pas un répertoire
if [ ! -r "$repToScan$irep" ]; then # si fichier non lisible (read)
text+="$repToScan$irep : inaccessible en lecture \n"
continue # suivant dans la boucle
fi
# traitements fichier
[[ "$irep" == "uevent" || "$irep" == "modalias" ]] && rc=" \n" || unset rc
tempo="$(strings -aw -n1 $repToScan$irep)" # au moins 1 caractère, inclus white space, all tout le fichier
[ "$tempo" ] && text+="$irep: $rc$tempo \n" || text+="$irep: <vide> \n"
fi
prof=$(( prof-1 )) # niveau--
done
[ "$fileOutput" ] && echo -e "$text" >> "$fileOutput" # sauvegarde dans fichier si $fileOutput défini
[ "$fileOutput" ] || echo -e "$text" # affichage si $fileOutput non défini
}
# $1=cmd si $2: nb de tentatives pour s'identifier, sinon 2 tentatives par défaut
f__sudo(){ # 22/10/2017
local nb=2 sudo isudo
# sudo --shell bash équivalent su ?
if sudo -v &>/dev/null && [ $EUID -ne 0 ] ; then
sudo="sudo su --shell $(f__which bash) --preserve-environment -c "
else
sudo="su --shell $(f__which bash) --preserve-environment -c "
fi
[ "$2" ] && nb="$2"
for (( isudo=1 ; isudo<="$nb" ; isudo++ )); do
$sudo " $1"
[ "$?" == 0 ] && break
[ "$isudo" == "$nb" ] && return 1
done
}
# user ayant initié la session graphique, assigne $user_
# return 1 sur échec identification user, return 2 sur absence home/
# gestion variable environnement user avec: USER_INSTALL=user script
f__user(){ # 09/10/2017
local user_id 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
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
user_="$root_login"
return 0
fi
fi
if [ "$SUDO_UID" ]; then
user_id="$SUDO_UID";
elif grep -qEo '[0-9]+' <<< "$XDG_RUNTIME_DIR" ; then
user_id="$(grep -Eo '[0-9]+' <<< $XDG_RUNTIME_DIR | cut -d'/' -f4)"
elif grep -qEo '[0-9]+' <<< "$XAUTHORITY" ; then
user_id="$(grep -Eo '[0-9]+' <<< $XAUTHORITY | cut -d'/' -f4)"
fi
[ "$user_id" ] && user_="$(grep $user_id /etc/passwd | cut -d ":" -f 1 )"
if [ "$user_" ] && [ "$user_" != "$root_login" ]; then
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
if [ -z "$user_" ]; then return 1; fi
if [ ! -d "/home/$user_" ]; then return 2; fi
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, sortie du script si $1 seul (même si url testée ok)
# si $2=print affiche url testée & entêtes http & location (si présente) et sortie normale fonction
# si $2=loc affiche seulement location et sortie normale fonction
# si $2=test return 0 si ok, return 1 si ko
f__wget_test(){ # 06/11/2017
local file_test_wget retourWget retourHttp location
file_test_wget="/tmp/testWget-$$-$RANDOM"
wget -Sq --timeout=10 --user-agent="$user_agent" --spider --save-headers "$1" &>"$file_test_wget"
retourWget="$?"
[ "$retourWget" == 1 ] && retourWget="code erreur générique"
[ "$retourWget" == 2 ] && retourWget="parse erreur (ligne de commande?)"
[ "$retourWget" == 3 ] && retourWget="erreur Entrée/sortie fichier"
[ "$retourWget" == 4 ] && retourWget="défaut réseau"
[ "$retourWget" == 5 ] && retourWget="défaut vérification SSL"
[ "$retourWget" == 6 ] && retourWget="défaut authentification"
[ "$retourWget" == 7 ] && retourWget="erreur de protocole"
[ "$retourWget" == 8 ] && retourWget="réponse serveur en erreur"
retourHttp="$(grep -i 'HTTP/' "$file_test_wget" | tr -d '\n' | xargs)"
if [ "$2" == "test" ]; then
rm "$file_test_wget" 2>/dev/null
# spécial maintenance frama.link
[ "$(grep -c '303' <<< $retourHttp)" -ne 0 ] && return 1 # 303 See Other
[ "$retourWget" == "0" ] && return 0 || return 1
fi
location="$(grep -i 'location' $file_test_wget | xargs)"
if [ "$2" == "print" ]; then
if [ "$retourWget" ]; then
echo "erreur wget: $RED$retourWget"
echo -e "$BLUE $1$STD\t$RED $retourHttp"
else
echo -e "$BLUE $1$STD\t$GREEN $retourHttp"
fi
fi
if [ "$2" == "print" ] || [ "$2" == "loc" ]; then
[ "$location" ] && echo "$YELLOW $location" || echo "$YELLOW no location"
echo "$STD"
return 0
fi
if [ "$retourWget" ]; then
rm "$file_test_wget"
f__error "wget, $retourWget" "$1" "$YELLOW$retourHttp" "location"
fi
if [ "$(grep -c '200' <<< $retourHttp)" -ne 0 ]; then
echo -e "$GREEN\ntout est ok, réessayer\n$STD"
fi
rm "$file_test_wget" 2>/dev/null
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
}
# $1 variable à afficher, $2 type de titre var|cmd|sans|+:text|+:vide [$3 titre] [$4 commentaire]
# $2: cmd->`titre`, var->**titre**, sans: pas de titre
# :text ajouté, affiche le text en liste (avec puce)
# :vide bypass le test de contenu $1, affiche 'vide', si besoin, en liste
# "variable" "sans" "" "comment" -> pas de titre mais commentaire encadré
# passage en paramètre variable et pas $variable
# un test si variable $1 est vide est fait sauf ':vide'
# un test si variable $1 contient 'nofile' (non trouvé par f_grep_file)
# f_display "variable" "type" "titre" "commentaire"
f_display(){ # 20/11/2017
[[ "${!1}" || "$2" =~ :vide ]] || return 0 # test si contenu dans $1
local display="" toDisplay="${!1}"
# flush, avant fonction, de $text parent
[ "$text" ] && echo -en "$text" >> "$fileOutput"
unset text
# traitement ligne de titre
[ "$toDisplay" ] || toDisplay="vide" # cas si :vide
[[ "$2" =~ sans|var|cmd ]] || display=" **⚡ erreur f_display \$2 ($1 $2 $3) ⚡** \n" # test $2 valide
[[ "$2" =~ "var" ]] && display="**$3**" # type var, titre en gras
[[ "$2" =~ "cmd" ]] && display="\`$3\`" # type cmd, titre entre backtick
[ "$4" ] && display+="$spc5( $4 )" # +$4 en gras avec 5 espaces insécables avant
# [ "$2" == "sans" ] || display+=" \n"
display+=" \n"
# traitement contenu
if [ "$toDisplay" == "nofile" ]; then # renvoyé par f_grep
display+="\n* fichier $1 non trouvé \n"
elif [[ "$2" =~ :text || "$toDisplay" == "vide" ]]; then
display+="\n* $toDisplay \n"
else
display+='``` \n'
display+="$toDisplay \n"
display+='``` \n'
fi
echo -en "$display\n" >> "$fileOutput" # flush fonction
}
# $1 variable à afficher en alerte/info, [$2 alert|info] type de message, alert par défaut
# passage en paramètre variable et pas $variable
# un test si variable $1 est vide ou non est fait
f_dspl_alert(){ # 21/11/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\n"
[ "$type" == "info" ] && display="${!1} \n\n"
echo -en "$display\n" >> "$fileOutput" # flush fonction
}
# conversion markdown pour affichage en console, $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_dspl_md(){ # 27/11/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=$(< $1)
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"
display=${display//\\/\\\\} # echappement des antislash, utile pour efiboot
while read 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 répertoire à scanner, $2 profondeur
f_dspl_scandir(){ # 21/10/2017
[ "$text" ] && echo -e "$text" >> "$fileOutput" # flush avant fonction
unset text
local text
text="\`$1 $2\` \n"
text+='``` \n'
echo -e "$text" >> "$fileOutput" # flush avant scandir
unset text
if [ -d "$1" ]; then
f__scandir $1 $2
else
text="$1 inexistant \n"
fi
text+='``` \n'
echo -e "$text" >> "$fileOutput" # flush fonction
}
# $1=liste fichier(s) à grepper, [$2]: largeur 1ère colonne &| nofile &| novide &| ligneVide
# si aucun fichier dans la liste retour: 'nofile|vide|inexistant
# si novide pas d'indication vide
# si 'notitre' pas d'énumération de fichier greppé (destiné à un seul fichier)
# si 'noinexist' pas de titre si fichier inexistant
# si lignevide, pas de suppression des lignes vides
# si date, date de modification du fichier
# ex. cumul option: "10 novide nofile lignevide"
# cmd de base: grep -Ersv '^#|^$' file|dossier
f_grep_file(){ # 27/11/2017
local file content display
for file in $1; do
# contenu
if [[ "${2,,}" =~ lignevide ]]; then
content=$( grep -Ersv '^[[:blank:]]*#' "$file")
else
content=$( grep -Ersv '^[[:blank:]]*#|^[[:blank:]]*$' "$file")
fi
if [[ "$2" =~ [0-9] ]]; then # si $2 contient des chiffres (largeur), gawk
content=$(gawk -v "larg=${2//[[:alpha:]]}" '
/^[[:graph:]]/ { printf "%-"larg"s",$1; $1=""; printf "%s\n",$0 } # graph exclut ligne vide ou retour grep vide
' <<< "$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
else
[[ "${2,,}" =~ "noinexist" ]] || display+=" $file: inexistant"$'\n\n'
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$urlNotice\n$STD"
}
fi_batt(){ # 10/11/2017
local pluriel
[ "$fg_nb_batt" ] || figet_batt
[[ "$fg_nb_batt" == "-1" || "$fg_nb_batt" -gt 0 ]] || return 0 # pas de batterie
###
[ "$fg_nb_batt" -gt 1 ] && pluriel="s" || unset pluriel
text="## batterie"$pluriel" \n\n"
f_display "fg_batt" "sans"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_conf(){ # 27/11/2017
local confs file grepP toScrut=(
/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
)
confs=$( f_grep_file "${toScrut[*]}" "noinexist" )
for file in ${toScrut[*]}; do
[ -e "$file" ] && grepP+=" $file" # fichiers présents
done
###
text="## fichiers configuration divers \n\n"
f_display "confs" "cmd" "grep -Ersv '^#|^$' $grepP"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_cpu(){ # 19/11/2017
local cpu_flags text iflag var_temp qte_flags text_flags="" pluriel
cpu_flags=$( sed -n 's/^flags.*: \(.*\)$/\1/p;' /proc/cpuinfo | sed -n '1p'| \
tr ' ' '\n' | sort | tr '\n' ' ' | xargs )
[ "$CPU_FLAGS" ] || figet_cpu_flags # appel 'base' des tags, obtention $CPU_FLAGS
for iflag in $cpu_flags; do
var_temp=$( grep -E "^${iflag^^}[[:blank:]]" <<< $CPU_FLAGS )
[ "$var_temp" ] && text_flags+="$var_temp \n" || text_flags+="$iflag\t⟷ \t? \n"
done
[ "$cpu_flags" ] && qte_flags=$( f__wcv -w "$cpu_flags" flags )
[ "$fg_cpu" ] || figet_cpu
###
[ ${fg_cpu:0:1} -gt 1 ] && pluriel="s" || unset pluriel
text="## processeur"$pluriel" \n\n"
f_display "fg_cpu" "cmd" "lscpu" # affichage proc
f_display "fg_uarch" "var" "µarchitecture processeur"
f_display "cpu_flags" "var" "$qte_flags flags cpu" # flags cpu bruts
f_display "text_flags" "sans" # flags cpu texte
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_disk(){ # 27/11/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
[ "$fg_nb_disk" ] || figet_disk
# éventuellement 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
text="## disque"$pluriel" \n\n"
# espace des partitions fixes montées
text+="* $(gawk -F': ' '{print $1": **"$2"**"}' <<< $fg_disk_part_fix_tot) \n\n"
text+='``` \n'
# disques fixes et amovibles
[ "$(wc -w <<< $fg_disk_fixe)" -gt 1 ] && pluriel="s" || unset pluriel
text+="$(printf '%-17s: %s' "disque$pluriel fixe$pluriel" "$fg_disk_fixe") \n"
[ "$(wc -w <<< $fg_disk_amov)" -gt 1 ] && pluriel="s" || unset pluriel
text+="$(printf '%-17s: %s' "disque$pluriel amovible$pluriel" "$fg_disk_amov") \n\n"
# partitions fixes montées / swap / non montées
[ "$(wc -w <<< $fg_disk_part_fixe_m)" -gt 1 ] && pluriel="s" || unset pluriel
text+="$(printf '%-24s: %s' "partition$pluriel fixe$pluriel montée$pluriel" "$fg_disk_part_fixe_m") \n"
[ "$(wc -w <<< $fg_disk_part_swap)" -gt 1 ] && pluriel="s" || unset pluriel
text+="$(printf '%-24s: %s' "partition$pluriel swap$pluriel" "$fg_disk_part_swap") \n"
[ "$(wc -w <<< $fg_disk_part_fixe_nm)" -gt 1 ] && pluriel="s" || unset pluriel
text+="$(printf '%-28s: %s' "partition$pluriel fixe$pluriel non montée$pluriel" "$fg_disk_part_fixe_nm") \n\n"
# partitions amovibles montées / non montées
[ "$(wc -w <<< $fg_disk_part_amov_m)" -gt 1 ] && pluriel="s" || unset pluriel
text+="$(printf '%-32s: %s' "partition$pluriel amovible$pluriel montée$pluriel" "$fg_disk_part_amov_m") \n"
[ "$(wc -w <<< $fg_disk_part_amov_nm)" -gt 1 ] && pluriel="s" || unset pluriel
text+="$(printf '%-32s: %s' "partition$pluriel amovible$pluriel non montée$pluriel" "$fg_disk_part_amov_nm") \n\n"
# détails des disques par type
text+="$fg_disk_table \n"
text+='``` \n\n'
text+="**types de disque** \n\n"
text+="| sata | usb | mmc | nvme | \n"
text+="| :---: | :---: | :---: | :---: | \n"
text+="| $fg_disk_ata | $fg_disk_usb | $fg_disk_mmc | $fg_disk_nvme | \n\n"
# éventuellement hddtemp
f_display "dd_temp" "cmd" "$cmd_dd_temp" "température disques"
f_dspl_alert "alert_dd_temp" "info"
# df, espaces des partitions montées seules
f_display "disk_df" "cmd" "$cmd_dfh" "utilisation disques"
# df -i, inoeuds
f_display "disk_df_i" "cmd" "$cmd_dfi" "utilisation inoeuds"
# lsblk répertoire disques & partitions
f_display "disk_lsblk" "cmd" "lsblk -o NAME,FSTYPE,SIZE,LABEL,MOUNTPOINT,UUID" \
"disques & partitions"
# fstab
f_display "fstab" "cmd" "grep -Ev '^#|^$' /etc/fstab" "fstab"
# resume
f_display "resume" "cmd" "grep -Evs '^#|^$' /etc/initramfs-tools/conf.d/resume" \
"resume"
f_dspl_alert "alert_file_resume" "info"
f_dspl_alert "alert_uuidResume" "alert"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_dmesg(){ # 27/11/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 $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-"*
###
text="## dmesg kernel (emergency, alerte, erreur, warning ou critique) \n\n"
f_display "dmesg_emerg" "cmd" "dmesg -l emerg" "emergency, $nb_lignes premières lignes"
f_display "dmesg_alert" "cmd" "dmesg -l alert" "alerte, $nb_lignes premières lignes"
f_display "dmesg_crit" "cmd" "dmesg -l crit" "critique, $nb_lignes premières lignes"
f_display "dmesg_err" "cmd" "dmesg -l err" "erreur, $nb_lignes premières lignes"
f_display "dmesg_warn" "cmd" "dmesg -l warn" "warning, $nb_lignes premières lignes"
text+="**les $nb_lignes premières lignes commencent à la date la plus ancienne encore dans les logs kernel** \n\n"
f_dspl_alert "alert_firmBug" "alert"
f_dspl_alert "info_ucode" "info"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_efi(){ # 20/11/2017
local efiboot text
[ $( f__which efibootmgr ) ] || return 0
efiboot=$( gawk '
/^Boot0/ { gsub(/\\/,"\\\\",$3); printf "%s %s: \n %s \n", $1, $2, $3 };
! /^Boot0/ { print $0 }
' <<< $( efibootmgr -v 2>/dev/null ) )
###
text="## EFI boot manager \n\n"
f_display "efiboot" "cmd" "efibootmgr -v" "config EFI boot"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_graph(){ # 27/11/2017
local slots cards cmd_cards ig
local stck_glxinfo stck_glxinfoOpt stck_glxinfoDri glx_dvc cmd_glx_dvc glx_dvc_temp openGl cmd_openGl
local providers resolutions pluriel modules cmt_modules text
local alert_hybrid alert_3D alert_Wayland
# cardsManuel="$(lspci -nnk | grep -EiA 3 'vga|display|3d')" # -nn: textual and numeric ID's, k kernel
# cardsManuel="$(lspci -nnv | grep -iEA11 'vga|display|3d)" # v=verbose
# cardsManuel="lspci -nnv -s $( lspci | grep -Ei 'vga|display|3d' | cut -d" " -f1 )" si plusieurs devices possibles??
[ "$fg_nb_gpu" ] || figet_gpu
[ "$fg_nb_gpu" -eq 0 ] && return 0 # pas de gpu, rien à voir
# slots pci video
slots="$(lspci | grep -Ei 'vga|display|3d' | cut -d" " -f1)"
# lspci
cmd_cards="lspci -nnv | grep -iEA11 'vga|display|3d'" # commande par défaut
if ! lspci -nnv &>/dev/null ; then # commande/option indisponible
cards="lspci -nnv non disponible"$'\n'
elif [ "$fg_nb_gpu" -gt 1 ]; then # plusieurs cartes, essai optirun ou prime
if [ $( f__which optirun ) ]; then
for ig in $slots; do
cards+=$( optirun lspci -nnv -s $ig )$'\n'
done
cmd_cards="optirun $cmd_cards"
else # DRI
for ig in $slots; do
cards+=$( DRI_PRIME=1 lspci -nnv -s $ig )$'\n'
done
cmd_cards="DRI_PRIME=1 cmd_cards"
fi
else
cards+=$( lspci -nnv -s $slots )$'\n' # une seule carte
fi
cards=${cards//(prog-if*])} #suppression (prog-if...])
[ "$cards" ] && cards=${cards::-1} # suppression dernier $'\n'
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
# $1="[opt|dri]", assigne $openGl pour un ou plusieurs gpu (dri & optirun) & $cmd_openGl
fi_graph_openGl(){
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}
}
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 [ "$fg_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_graph_openGl # openGl pour une carte ou gpu de base
if [ "$fg_nb_gpu" -gt 1 ]; then # plusieurs cartes, optirun et prime
if [ $( f__which optirun ) ]; then
fi_graph_openGl "opt" # ajout à $openGl existant, pas de redondance
cmd_openGl="optirun glxinfo"
else # DRI
fi_graph_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
modules="$(lsmod | grep -Ei 'amdgpu|ati|i915|nouveau|nvidia|radeon|video|gma')"
cmt_modules="modules recherchés: amdgpu, ati, i915, nouveau, nvidia, radeon, video, gma"
# fonctions externes
[ "$fg_resolution" ] || figet_screen
###
text="## graphisme \n\n"
[ "$fg_gpu" ] && text+="$(sed -E 's/(.*)/> \* \*\*\1\*\*/' <<< $fg_gpu) \n\n" # mise en puces + quote
# nb écran & résolution(s) active(s)
text+="nombre d'écrans: **$fg_nb_screen** \n"
[ $( f__wcv "-wv" "$fg_resolution" "pixels" ) -gt 1 ] && pluriel="s" || unset pluriel
text+="résolution"$pluriel" active"$pluriel": **$fg_resolution** \n\n"
# lspci -nnv
f_display "cards" "cmd" "$cmd_cards"
f_dspl_alert "alert_hybrid" "alert"
# wayland
f_dspl_alert "alert_Wayland" "info"
# openGl
f_display "glx_dvc" "cmd" "$cmd_glx_dvc" "devices OpenGl"
f_dspl_alert "alert_3D" "info"
f_display "openGl" "cmd" "$cmd_openGl" "OpenGl"
# liste providers, preferred & current
f_display "current_preferred" "cmd" "$cmd_resolutions" "$cmt_resolutions"
f_display "providers" "cmd" "$cmd_providers"
# résolutions possibles, pas d'affichage si mode (ssh) ou xrandr pas accessible
f_display "resolutions" "cmd" "$cmd_resolutions" "$cmt_resolutions"
# modules vidéo
if [ "$modules" ]; then
f_display "modules" "var" "modules vidéo" "$cmt_modules"
else
text+="Modules non reconnus. Il serait bien de communiquer le retour de \`lsmod\` \n"
text+="merci de contacter $projet: \n$contact "
fi
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_hw(){ # 25/11/2017
[ "$fg_hw" ] || figet_hw
###
text="## hardware monitor ACPI \n\n"
f_display "fg_hw" "sans"
[ "$fg_hw" ] || text+="* **pas d'informations détectées** \n\n"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_journal(){ # 27/11/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 2>/dev/null ) ] && dmesg -Hk --nopager | grep -i 'Firmware Bug' > $file-firmBug ; \
chown $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-"*
###
# kernel
text="## journalctl kernel (emergency, alert, erreur, warning ou critique) \n\n"
[ "$alert_jctl_persist" ] || text+="**journaux persistants** \n\n"
f_dspl_alert "alert_jctl_persist" "info"
text+="* Début des log: **$jctl_boot** \n\n"
# journaux kernel
f_display "jctl_alert_k" "cmd" "journalctl --no-hostname -b0 -k -p1" \
"**kernel emergency 0 & alerte 1**, $nb_lignes premières lignes"
f_display "jctl_crit_k" "cmd" "journalctl --no-hostname -b 0 -k -p 2..2" \
"**kernel critique**, $nb_lignes premières lignes"
f_display "jctl_err_k" "cmd" "journalctl --no-hostname -b0 -k -p 3..3" \
"**kernel erreur**, $nb_lignes premières lignes)"
f_display "jctl_warn_k" "cmd" "journalctl --no-hostname -b0 -k -p 4..4" \
"**kernel warning**, $nb_lignes premières lignes"
# journaux hors kernel
text+="## journalctl hors kernel (emergency, alert, erreur, warning ou critique) \n\n"
text+="* Début des log: **$jctl_boot** \n\n"
f_display "jctl_alert_nok" "cmd" "journalctl --no-hostname -b0 -p 1 | grep -v kernel" \
"**hors kernel, emergency 0 & alerte 1**, $nb_lignes premières lignes"
f_display "jctl_crit_nok" "cmd" "journalctl --no-hostname -b0 -p 2..2 | grep -v kernel" \
"**hors kernel, critique**, $nb_lignes premières lignes"
f_display "jctl_err_nok" "cmd" "journalctl --no-hostname -b0 -p 3..3 | grep -v kernel" \
"**hors kernel, erreur**, $nb_lignes premières lignes"
f_display "jctl_warn_nok" "cmd" "journalctl --no-hostname -b0 -p 4..4 | grep -v kernel" \
"**hors kernel, warning**, $nb_lignes premières lignes"
#informations
text+="* les $nb_lignes premières lignes commencent à la date du dernier boot \n\n"
f_display "jctl_size" "cmd" "journalctl --disk-usage " "taille des journaux"
# dernières lignes
f_display "jctl_last" "cmd" "journalctl --no-pager --no-hostname -b0 -p 4 -n25" \
"**toutes provenance, emergency-warning**, $nb_lignes lignes les plus **récentes**"
f_dspl_alert "alert_firmBug" "alert"
f_dspl_alert "info_ucode" "info"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_locale(){ # 25/11/2017
local locale localectl timezone timedatectl xKeyboardMap keyboard text
local alert_rtc alert_ntp
# locale
locale="$(f_grep_file "/etc/default/locale* /etc/locale.conf")"
[ $( f__which localectl ) ] && localectl=$( localectl --no-pager status )
# 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
###
text="## localisation \n\n"
# locale
f_display "locale" "cmd" "grep -Esv '#|^$' /etc/default/locale* /etc/locale.conf"
f_display "localectl" "cmd" "localectl --no-pager status"
# timezone
f_display "timezone" "cmd" "grep -EHsv '#|^$' /etc/timezone*"
f_display "timedatectl" "cmd" "timedatectl status --no-pager"
f_dspl_alert "alert_ntp" "info"
f_dspl_alert "alert_rtc" "alert"
# keyboard layout
f_display "keyboard" "cmd" "grep -EHv '#|^$' /etc/default/keyboard*"
f_display "xKeyboardMap" "cmd" "setxkbmap -query"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_log_xorg(){ # 27/11/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
toScrut=(
/var/log/Xorg.0.log
/home/$user_/.local/share/xorg/Xorg.0.log
/var/lib/gdm3/.local/share/xorg/Xorg.0.log
)
# checkpoint
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"
###
text="## journaux Xorg \n\n"
f_display "logXorg" "cmd" "$cmd_logXorg" "$cmt_logXorg"
f_dspl_alert "info_logs" "info"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_mem(){ # 20/11/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 )
###
text="## mémoire \n\n"
f_display "memoire" "cmd" "free -h"
f_display "swappiness" "cmd" "cat /proc/sys/vm/swappiness"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_nm(){ # 23/11/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}' )
###
text="## NetworkManager \n\n"
f_display "nm_etat" "cmd" "$cmd_nm_etat" "$cmt_nm_etat"
f_display "nm_conf" "cmd" "$cmd_nm_conf" "$cmt_nm_conf"
f_display "nm_wifis" "cmd" "$cmd_nm_wifis" "$cmt_nm_wifis"
echo -en "$text\n" >> "$fileOutput"
unset text
}
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 20/11/2017
local dateMaj nb_packages ifile info_update text pluriel
local sources cmt_sources cmd_sources
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 cmd_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 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
# 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."
# sources & 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' )
sources=$( f_grep_file "/etc/apt/sources.list /etc/apt/sources.list.d/*.list" 8 )
cmt_sources="dépôts"
cmd_sources="grep -Ersv '^#|^$' /etc/apt/sources.list /etc/apt/sources.list.d/*.list"
if [ $( ls -1 /etc/apt/sources.list.d/ | grep -cEv '\.list$' ) -gt 0 ]; then
for ifile in $( ls /etc/apt/sources.list.d/* ); do
if [[ ${ifile##*.} != "list" ]]; then
alert_non_list+="$ifile: ignoré, extension non valable"
fi
done
fi
# 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
# apt prefs
apt_prefs=$( f_grep_file "/etc/apt/preferences.d/*" )
cmt_apt_prefs="préférences apt"
cmd_apt_prefs="grep -Erv '^#|^$' /etc/apt/preferences.d/"
printf "◇"
# 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)"
cmd_notUpgraded=""
alert_full_upgrade="ces paquets peuvent être mis à jour avec avec: **apt full-upgrade**"
fi
printf "◇"
# 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
printf "◇"
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__wcv -l "$( ls -1 /var/cache/apt/archives/ )" )
[ "$qte_clean" -gt 1 ] && pluriel="s" || unset pluriel
cmt_clean="taille du cache des paquets"
cmd_clean="du -chS /var/cache/apt/archives/"
if [ "$size_clean" -gt 200 ]; 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 %-20s %-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 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"
}
###
text="## gestion de paquets **${1#*:}** \n\n"
text+="* nombre de paquets installés: **$nb_packages** \n"
text+="* dernière mise à jour apt: **$dateMaj** \n"
text+="* version apt: **$apt_version** \n"
text+="\n"
f_dspl_alert "info_update" "info"
f_display "sources" "cmd" "$cmd_sources" "$cmt_sources"
f_dspl_alert "alert_https" "info"
f_dspl_alert "alert_httpsPossible" "info"
f_dspl_alert "alert_non_list" "info"
f_dspl_alert "alert_httpredir" "info"
f_display "apt_prefs" "cmd" "$cmd_apt_prefs" "$cmt_apt_prefs"
f_display "upgrade" "cmd:vide" "$cmd_upgrade" "$cmt_upgrade"
f_dspl_alert "alert_upgrade" "info"
f_dspl_alert "alert_apt" "alerte"
f_display "notUpgraded" "var" "$cmd_notUpgraded" "$cmt_notUpgraded"
f_dspl_alert "alert_full_upgrade" "info"
f_display "toRemove" "cmd:vide" "$cmd_toRemove" "$cmt_toRemove"
f_dspl_alert "alert_remove" "info"
f_display "autoclean" "cmd:vide" "$cmd_autoclean" "$cmt_autoclean"
f_dspl_alert "alert_autoclean" "info"
f_display "clean" "cmd:vide" "$cmd_clean" "$cmt_clean"
f_dspl_alert "alert_clean" "info"
f_display "non_ii" "cmd:vide" "$cmd_non_ii" "$cmt_non_ii"
f_dspl_alert "alert_non_ii" "info"
[ $( f__which deborphan ) ] && f_display "deborphan" "cmd:vide" "$cmd_deborphan" "$cmt_deborphan"
[ $( f__which deborphan ) ] && f_dspl_alert "alert_deborphan" "info"
f_display "holded" "cmd:vide" "$cmd_holded" "$cmt_holded"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_pkg_x(){ #v2 23/11/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=$( ls -1 /var/log/packages 2>/dev/null )
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=$( ls -1 /var/lib/eopkg/package 2>/dev/null )
nb_packages=$( f__wcv -l "$nb_packages")
cmd_nbPackages="wc -l <<< \$(ls -1 /var/lib/eopkg/package)"
elif [[ ${1#*:} == "Guix" ]]; then # Gnu Guix
nb_packages=$( ls -1 /gnu/store/*/ 2>/dev/null )
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=$( ls -d -1 /nix/store/*/ 2>/dev/null )
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
###
text="## gestion de paquets **${1#*:}** \n\n"
f_display "nb_packages" "cmd:text" "$cmd_nbPackages" "nombre de paquets installés"
f_display "sources" "cmd" "$cmd_sources" "sources"
f_display "holded" "cmd" "$cmd_holded" "paquets figés"
f_display "alert_pkg_todo" "var" "aide souhaitée"
}
fi_reseau(){ # 27/11/2017
local slots cards ip_a iwconfig interfaces route resolv canal_wifi ifx text pluriel
local alert_wlx alert_ifconfig
# cardsManuel="$(lspci -nnk | grep -EiA 5 'network|ethernet')"
# cardsManuel="$(lspci -nnv | grep -EiA 15 'network|ethernet')"
# cardsManuel="lspci -nnv -s $( lspci | grep -Ei 'network|ethernet' | cut -d" " -f1 )" si devices plusieurs slots???
#lspci
slots="$(lspci | grep -Ei 'network|ethernet' | cut -d" " -f1)"
for ifx in $slots; do
cards+=$( lspci -s $ifx -nnv )$'\n'
done
cards=${cards//(prog-if*])} #suppression (prog-if...])
[ "$cards" ] && cards=${cards::-1} # suppression dernier $'\n'
[ $( f__wcv -l "$cards" ) -eq 0 ] && cards="lspci incompatible"
# ip a & route
ip_a=$( ip a | sed '/link\/ether/d; /valid_lft/d' ) # filtre sur adr MAC & bail
# ip_a=$( sed '/inet6.*scope global/d; /inet6.*scope link/d' <<< $ip_a ) # filtre sur inet6 scope global & scope link (fe80::)
ip_a=$( sed '/inet6.*/d' <<< $ip_a ) # filtre sur inet6)
route=$( ip 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
if [ $( f__which iwconfig ) ]; then #paquet wireless-tools requis
iwconfig=$( LC_ALL=C iwconfig 2>&1 | grep -v 'no wireless extensions' | grep -v '^[[:space:]]*$' )
fi
# iwlist
if [ $( f__which iwlist ) ]; then # canal wifi utilisé; /sbin, paquet wireless-tools requis
canal_wifi=$( LC_ALL=C iwlist chan 2>&1 | grep 'Current Frequency' | grep -Eio 'channel [0-9]+' )
fi
# network manager
netmgrpaths=("/usr/sbin/NetworkManager" "/usr/sbin/wicd" "/usr/sbin/connmand") # thanks wireless-info
netmgrnames=("NetworkManager" "Wicd" "ConnMan")
for ifx in "${!netmgrpaths[@]}"; do
[ -e "${netmgrpaths[$ifx]}" ] && netmgrinst+=${netmgrnames[$ifx]}
if [ $( ps -ef | grep -c ${netmgrpaths[$ifx]} ) -ge 2 ]; then
netmgrrun+="$(ps -ef | grep -o "${netmgrpaths[$ifx]}.*$" | head -n 1)"
fi
done
figet_ip
if grep -iq 'wlx' <<< "$fg_ifn"; then
alert_wlx="Une interface wifi est en erreur: $(grep -o 'wlx' <<< $fg_ifn) \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
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
[ "$fg_mod_net" ] || figet_mod_net
###
# text="## réseau \n\n"
#lspci
f_display "cards" "cmd" "lspci -nnv | grep -EiA 15 'network|ethernet"
# ip locales avec type
[ $(f__wcv "-l" "$fg_ip_tp") -gt 1 ] && pluriel="s" || unset pluriel
f_display "fg_ip_tp" "sans" "" "IP locale"$plurielD
f_dspl_alert "alert_wlx" "alert"
text+="* les adresses Mac peuvent être affichées avec \`$DIRNAME""getInfo --mac\` \n"
text+="* l'IP publique peut être connue avec: \`$DIRNAME""getInfo --ip\` \n\n"
# gateways
[ $(f__wcv "-l" "$fg_gws") -gt 1 ] && pluriel="s" || unset pluriel
f_display "fg_gws" "sans" "" "Passerelle"$pluriel
# interface prioritaire
if [ $(wc -w <<< $fg_ifn) -gt 1 ]; then
f_display "fg_ifn_prior" "sans" "" "interface de sortie"
fi
# ip a & route & interface & resolv
f_display "ip_a" "cmd" "ip address" "sans ipV6 et sans adresses MAC"
f_display "route" "cmd" "ip route show"
f_display "interfaces" "cmd" "grep -EHrsv '#|^$' /etc/network/interfaces*" "configuration manuelle"
f_display "resolv" "cmd" "cat /etc/resolv.conf" "serveurs de noms DNS utilisés"
# iwconfig & iwlist
f_display "iwconfig" "cmd" "iwconfig" "état carte wifi"
if [ "$canal_wifi" ]; then
f_display "canal_wifi" "cmd" "iwlist chan | grep 'Current Frequency' | grep -Eio 'channel [0-9]+'" \
"canal wifi utilisé"
text+="* la configuration ssid utilisée peut être connue (si NetworkManager utilisé) avec "
text+="\`$DIRNAME""getInfo --ssid\` \n\n"
fi
# network manager
text+="* **gestionnaire de réseau** \n"
if [ "$netmgrinst" ]; then
[ $(wc -w <<< $netmgrinst) -gt 1 ] && pluriel="s" || unset pluriel
text+=" * installé"$pluriel": **$netmgrinst** \n"
text+=" * en fonctionnement: **$netmgrrun** \n\n"
else
text+=" * non trouvé parmi: ${netmgrnames[@]} \n"
fi
# modules réseau
f_display "fg_mod_net" "var" "modules réseau" "liste non garantie complète"
[ "$fg_mod_net" ] || text+="**Modules chargés non reconnus**"
f_dspl_alert "alert_ifconfig" "info"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_serial(){ #v2 22/11/2017
local chassis_serial machineId text
[ "$fg_nb_disk" ] || figet_disk
[ "$fg_nb_batt" ] || figet_batt
chassis_serial=$( cat /sys/class/dmi/id/chassis_serial 2>/dev/null )
machineId=$( cat /etc/machine-id 2>/dev/null )
###
[ "$machineId" ] && text+="\n$BOLD ID MAchine: $BLUE$machineId \n\n$STD"
text+="$BOLD* N° Série: \n\n$STD"
[ "$fg_disk_serial" ] && text+="$GREEN * Disques: \n"
[ "$fg_disk_serial" ] && text+="$BLUE$fg_disk_serial \n\n$STD"
[ "$fg_batt_serial" ] && text+="$GREEN * Batteries \n"
[ "$fg_batt_serial" ] && text+="$BLUE$fg_batt_serial \n\n$STD"
[ "$chassis_serial" ] && text+="$GREEN * Chassis \n"
[ "$chassis_serial" ] && text+="$BLUE$chassis_serial \n\n$STD"
echo -en "$text"
unset text
}
fi_ssid(){ #v2 22/11/2017
local nm_ssid text
local fileOutput="/tmp/$RANDOM-$RANDOM" # ré-assigne sortie pour f_display
[ "$EUID" -eq 0 ] || f__error "Root requis"
[ $( f__which nmcli ) ] || f__error "NetworkManager requis"
nm_ssid=$( f_grep_file "/etc/NetworkManager/system-connections/*" "lignevide" )
###
f__info "$RED""Attention:$BLUE la clé du réseau wifi est visible"
text="## configuration(s) ssid networkmanager \n\n"
f_display "nm_ssid" "cmd" "grep -Ersv '#|^$' /etc/NetworkManager/system-connections/*"
echo -en "$text\n" >> "$fileOutput"
unset text
f_dspl_md "$fileOutput" "marge"
rm "$fileOutput"
}
fi_system_analyse(){ #v 25/11/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 $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"
###
text="## analyse boot systemd \n\n"
[ "$srvcFail" ] || text+="* pas de service en erreur \n\n"
f_display "bootTime" "cmd" "$cmd_bootTime" "$cmt_bootTime"
f_display "srvcFail" "cmd" "$cmd_srvcFail" "$cmt_srvcFail"
f_dspl_alert "info_services" "info"
f_dspl_alert "alert_srvcFail" "alert"
f_display "bootBlame" "cmd" "$cmd_bootBlame" "$cmt_bootBlame"
f_display "bootCritic" "cmd" "$cmd_bootCritic" "$cmt_bootCritic"
f_display "bootGraph" "cmd:text" "$cmd_bootGraph" "$cmt_bootGraph"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_systeme(){ # 27/11/2017
local mbr uname bootImage initDaemon serverX shells lastboot uptime charge pluriel text
local alimentation alim_total ligne date_install
local alert_SLiM alert_microcode
[ -d /sys/firmware/efi ] && mbr="EFI" || mbr="Legacy (mbr)"
uname=$( uname -rmo )
bootImage=$( gawk '/BOOT_IMAGE/ {print $1}' /proc/cmdline )
bootImage=$( gawk '{print $1}{i=2; while (i <= NF-1) { 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^}
serverX="${XDG_SESSION_TYPE^}" # normalement retourne wayland
[ "$wayland" ] && serverX="$wayland" # au cas où
[ "$serverX" ] || serverX="n/a"
[ "$ENV_DISPLAY" ] && serverX+=":no DISPLAY"
[ "$ENV_SSH" ] && serverX+=":ssh"
if [ $( grep -c 'AC' <<< $(ls /sys/class/power_supply/ 2>/dev/null) ) -gt 0 ]; then
alim_total=$( grep -cs . <<< $(ls /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
while read ligne; do
date_install=$ligne
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' )
uptime=$( LC_ALL=C uptime )
charge=${uptime/*average: } # suppression jusqu'à 'average: '
charge=${charge//, / } # remplacement global ', ' par ' '
charge=${charge//,/.} # remplacement global , par .
uptime=${uptime%%, *} # uptime -p parfois inexistant (alpine), suppression à la fin de ',[blancs]*' -> conservation premier 'champs' ifs ', '
uptime=${uptime/*up /depuis } # suppression début jusqu'à 'up '
uptime=${uptime//weeks/semaines} # remplacement global
uptime=${uptime//week/semaine} # remplacement global
uptime=${uptime//days/jours} # remplacement global
uptime=${uptime//day/jour} # remplacement global
uptime=${uptime//hours/h} # remplacement global
uptime=${uptime//hour/h} # remplacement global
uptime=${uptime//minutes/mn} # remplacement global
uptime=${uptime//minute/mn} # remplacement global
[ "$fg_nb_batt" ] || figet_batt
[ "$fg_cpu" ] || figet_cpu
[ "$fg_de" ] || figet_de
[ "$fg_nb_disk" ] || figet_disk
[ "$fg_distrib" ] || figet_distrib
[ "$fg_dsp_mngr" ] || figet_dm
[ "$fg_dmi" ] || figet_dmi
[ "$fg_nb_gpu" ] || figet_gpu
[ "$fg_resolution" ] || figet_screen
[ "$fg_shell" ] || figet_shell
[ "$fg_wm" ] || figet_wm
if [[ "$fg_dsp_mngr" =~ "slim" || "$fg_dsp_mngr_actif" =~ "slim" ]]; then
alert_SLiM="SLiM est un projet abandonné et peu compatible avec systemd"
fi
if ! figet_ucode ; then
alert_microcode="$fg_ucode"
[ "$ENV_DEB" ] && alert_microcode+="\n les installer: **apt install $ucode**"
fi
###
f__architecture || f__info "Architecture non supportée"
# text="## système \n\n"
text+="> **$fg_dmi** \n\n"
text+="* CPU \n"
text+=" * **$(sed -n '1p' <<< $fg_cpu)** \n"
text+="* GPU \n"
[ "$fg_nb_gpu" -eq 0 ] && text+=" * **pas de carte graphique détectée** \n" # pas de gpu
[ "$fg_gpu" ] && text+="$(sed -E 's/(.*)/ * **\1**/' <<<$fg_gpu) \n" || text+=" * n/a \n"
text+="* boot **$mbr** \n"
text+="* distribution **$fg_distrib** \n\n"
text+='``` \n'
text+="processeur: $fg_cpu_arch \n"
text+="architecture système: $architecture \n"
text+="uname: $uname \n"
text+="$bootImage \n"
text+="date d'installation: $date_install \n"
text+="démon d'initialisation: $initDaemon \n"
text+="serveur d'affichage: $serverX \n"
text+="nombre d'écrans: $fg_nb_screen \n"
[ "$(f__wcv "-wv" "$fg_resolution" "pixels")" -gt 1 ] && pluriel="s" || unset pluriel
text+="résolution"$pluriel": $fg_resolution \n"
[ "$(wc -w <<< $fg_dsp_mngr)" -gt 1 ] && pluriel="s" || unset pluriel
text+="display manager"$pluriel": $fg_dsp_mngr \n"
[ "$fg_dsp_mngr_actif" != "$fg_dsp_mngr" ] && text+="display manager actif: $fg_dsp_mngr_actif \n"
text+="desktop (DE): $fg_de \n"
text+="window manager: $fg_wm \n"
text+="shell actif: $fg_shell \n"
text+="shells installés: $fg_shells \n"
[ "$fg_disk_part_fix_tot" ] && text+="$fg_disk_part_fix_tot \n"
[ "$alimentation" ] && text+="$alimentation \n"
if [ "$fg_batt" ]; then
[ "$fg_nb_batt" -gt "1" ] && pluriel="s" || unset pluriel
text+="$fg_nb_batt batterie"$pluriel" présente$pluriel: \n"
text+="$(sed -En 's/^BAT(.*)$/ BAT\1/p' <<< $fg_batt) \n"
fi
text+="dernier boot: $lastboot, uptime: $uptime \n"
text+="charge système depuis les 1, 5 et 15 dernières minutes: $charge ($fg_nb_threads threads) \n"
text+='``` \n\n'
[[ -z "$alert_microcode" && "$fg_ucode" ]] && text+="* $fg_ucode \n\n"
f_dspl_alert "alert_SLiM" "info"
f_dspl_alert "alert_microcode" "info"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_usb(){ # 25/10/2017
local lsusb lsusb_t text
lsusb=$( lsusb )
lsusb_t=$( lsusb -t )
###
text="## USB \n\n"
f_display "lsusb" "cmd" "lsusb"
f_display "lsusb_t" "cmd" "lsusb -t"
echo -en "$text\n" >> "$fileOutput"
unset text
}
fi_vrms(){ # 20/11/2017
local vrms non_free contrib total text pluriel tempo
if [ $( f__which vrms ) ]; then
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
fi
###
text="## paquets non-libres \n\n"
if [ "$vrms" ]; then
f_display "vrms" "cmd" "vrms" "détection des paquets non libres par Richard M. Stallman"
else
text+="* les paquets non-free ou contrib ne peuvent être détectés sans l'installation de vrms \n"
fi
echo -en "$text\n" >> "$fileOutput"
unset text
}
# informations batterie(s), assigne $fg_nb_batt $fg_batt $fg_batt_serial
figet_batt(){ #v2 11/11/2017
local batt_detail batt_nb 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
if [ ! -d /sys/class/power_supply ]; then # anciennes interfaces ou inconnu
[ -d /proc/acpi/battery ] && batt_detail="ancienne interface ACPI non gérée (obsolète)"
[ -e /proc/apm ] && batt_detail="anciennes batteries APM non gérées (obolète)"
[ "$batt_detail" ] || batt_detail="répertoire power_supply inaccessible"
batt_nb="-1"
return 1
fi
[ "$(grep -c 'BAT' <<< $(ls /sys/class/power_supply/ 2>/dev/null))" -gt 0 ] || return 0
batt_nb="$(grep -i 'Battery' /sys/class/power_supply/*/type | grep -c .)"
[ "$batt_nb" ] || return
batRep="/sys/class/power_supply"
unset batt_detail
for ibat in $(ls $batRep); do
grep -qi 'Battery' "$batRep/$ibat/type" || continue # plus loin si non batterie
[ -e "$batRep/$ibat/uevent" ] || batt_detail="$ibat: **uevent** incorrect"
[ -e "$batRep/$ibat/uevent" ] || continue
uevent="$(grep -s . $batRep/$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 $batRep/$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: $(cat $batRep/$ibat/manufacturer 2>/dev/null) "
batt_detail+="($(cat $batRep/$ibat/model_name 2>/dev/null)) $(cat $batRep/$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
fg_nb_batt="$batt_nb"
[ "$batt_detail" ] && fg_batt=${batt_detail::-1} # suppression dernier $'\n'
[ "$(xargs <<< $fg_batt_serial)" ] || fg_batt_serial+="n/a"
}
# assigne $fg_cpu (3 lignes description cpu), fg_nb_threads, $fg_cpu_arch, $fg_uarch, $fg_vendor=AMD|Intel
figet_cpu(){ #v2 24/11/2017
local cpuinfo speedNom speedMax speedMin speedCpu descrCpu cpu1 cpu2 cpu3
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'
# traitement fg_cpu
cpu1=$(
gawk -v "speedCpu=$speedCpu" -F ':|@' '
/^model name/ { gsub(/^ | *$|\(R\)|\(TM\)|\(r\)|\(tm\)|CPU/,"",$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
[ "$fg_uarch" ] || figet_cpu_uarch
}
# stockage des flags cpu extraits du kernel, assigna $CPU_FLAGS
figet_cpu_flags(){ # 24/11/2017
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(){ # 24/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é"
[ "$fg_cpu" ] || 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
figet_de(){ #v 25/11/2017 # thanks neofetch
local de="n/a"
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'à /
de=${DESKTOP_SESSION##*=} # suppression plus grande chaine au début jusqu'à =
fi
# fallback to using xprop
if [[ "$wayland" && "$EUID" -eq 0 && -z "$de" ]]; then
fg_de="n/a:wayland root"
return 0
elif [[ -z "$de" ]]; then
de=$( xprop -root | gawk 'IGNORECASE = 1;/KDE_SESSION_VERSION|^_MUFFIN/' )
fi
# Format strings
if [[ "${de,,}" =~ kde_session_version ]]; then # test sur minuscules
de="kde"${de/* = }
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
}
# $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 22/11/2017
local size type list_id idisk lsblk vendor model rev serial
unset fg_disk_fixe fg_disk_amov
# 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 $(grep -v 'loop' <<< $(ls /sys/block/)); 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="espace des 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 23/11/2017
local prefix version
# 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
[ "$fg_distrib" ] && [[ $(grep -is 'chrome-' /proc/version) || -f "/dev/cros_ec" ]] && fg_distrib="$(lsb_release -sd 2>/dev/null)/xhrome-os"
[ "$fg_distrib" ] && [ $(grep -is 'microsoft' /proc/version) ] && fg_distrib="$(lsb_release -sd 2>/dev/null)/windows"
[ "$fg_distrib" ] || fg_distrib=$(lsb_release -sd 2>/dev/null)
# prefix sur nom fichier éventuels *[_-][version|release]
[ "$prefix" ] || prefix=$(ls /etc/*_version 2>/dev/null | sed -En 's#/etc/(.*)_version#\1#p')
[ "$prefix" ] || prefix=$(ls /etc/*-version 2>/dev/null | sed -En 's#/etc/(.*)-version#\1#p')
[ "$prefix" ] || prefix=$(ls /etc/*-release 2>/dev/null | grep -v 'os-release' | 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_dsp_mngr (liste) ou 'n/a', $fg_dsp_mngr_actif
figet_dm(){ #v1 27/11/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
fg_dsp_mngr=""
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_dsp_mngr+="${idm^} "
fg_dsp_mngr_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_dsp_mngr+="${idm^} "
fg_dsp_mngr_actif="${idm^}"
fi
done
fg_dsp_mngr=${fg_dsp_mngr% } # supression espace final
if [[ -z "$fg_dsp_mngr" && -e "/etc/X11/default-display-manager" ]]; then
x11=$(cat /etc/X11/default-display-manager)
fg_dsp_mngr=${x11##*/} # conservation dernier champs ifs '/'
fi
if [[ -z "$fg_dsp_mngr" && "${ps/*startx*/test}" == "test" ]]; then
fg_dsp_mngr="(startx)"
fg_dsp_mngr_actif="(startx)"
fi
fg_dsp_mngr_actif=${fg_dsp_mngr_actif^}
if [[ -z "$fg_dsp_mngr_actif" && $( type -p systemctl 2>/dev/null ) ]]; then
fg_dsp_mngr_actif=$(grep 'Main PID' <<< $(systemctl status display-manager))
fg_dsp_mngr_actif=${fg_dsp_mngr_actif##* } # conservation dernier champs ifs ' '
fg_dsp_mngr_actif=${fg_dsp_mngr_actif/\(/} # suppression (
fg_dsp_mngr_actif=${fg_dsp_mngr_actif/\)/} # suppression )
[ ${fg_dsp_mngr// } ] || fg_dsp_mngr="$fg_dsp_mngr_actif"
fi
[ "$fg_dsp_mngr" ] || fg_dsp_mngr="n/a"
[ "$fg_dsp_mngr_actif" ] || fg_dsp_mngr_actif="n/a"
}
# informations DMI, (firmware partie matériel), assigne $fg_dmi
figet_dmi(){ #v2 06/11/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
)
# 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=$(sed 's/x.xx*//; s/To be filled by O\.E\.M\.//g' <<< $tempo | xargs) # ménage
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
[ "$product" ] && fg_dmi=$(printf "%s: %s " "prod." "$product")$'\n'
[[ "$board" && "$indic1" != "$indic2" ]] && fg_dmi+=$(printf "%s: %s " "board" "$board")$'\n'
[ "$bios" ] && fg_dmi+=$(printf "%s : %s" "bios" "$bios")
}
# assigne $fg_gpu (liste des gpu), $fg_nb_gpu
# requis: f__wcv
figet_gpu(){ #v3 10/11/2017
local lspci field1
lspci="$(lspci -mm 2>/dev/null)"
if [ "$?" -eq 0 ]; then
# debug: lspci="$(< tests/lspci)"
fg_gpu="$(gawk -F' "|" "|" -' ' /"Display|"3D|"VGA/ {
sub(/ Corporation/,"",$3); sub(/Advanced Micro Devices, Inc. /,"",$3); sub(/ /," ",$3);
print $3": "$4}' <<< $lspci)"
else # lspci -mm en erreur, utilisation lspci (dans les requis)
read field1 lspci <<< $(IFS=':' lspci | grep -E 'Display |3D |VGA ') # lspci==VGA compatible controller: Intel Corporation System ...
fg_gpu=${lspci/*:/} # lspci==Intel Corporation System Controller ...
fg_gpu=${fg_gpu/ Corporation} # suppression ' Corporation'
fg_gpu=${fg_gpu/Advanced Micro Devices, Inc. } # suppression 'Advanced Micro Devices, Inc. '
fg_gpu=${fg_gpu/ / } # remplacement espace double par simple
fg_gpu=${fg_gpu## } # suppression du plus nombre d'espaces au début
fg_gpu=${fg_gpu%% } # suppression du plus nombre d'espaces à la fin
fi
fg_nb_gpu=$(f__wcv -l "$fg_gpu")
}
# infos température et fan via acpi, assigne $fg_hw
figet_hw(){ #v2 31/10/2017
local name labelF inputF labelT inputT critT hystT maxiT fan temp ihw
if [ ! -d /sys/class/hwmon/ ]; then
fg_hw="gestion acpi hwmon non accessible"
return 1
fi
unset fan temp
for ihw in $(ls /sys/class/hwmon/); do
[ -e /sys/class/hwmon/$ihw/name ] && name="$(cat /sys/class/hwmon/$ihw/name)" || name="indéfini"
## TEMPÉRATURE
if grep -Eq 'temp[0-9]+' <<< $(ls /sys/class/hwmon/$ihw/) ; then
# extraction label
# labelT=$(printf "%s/" "$(cat /sys/class/hwmon/$ihw/temp*_label 2>/dev/null)" | sed 's/ //g' | tr '\n' ' ')
labelT=$(printf "%s/" "$(cat /sys/class/hwmon/$ihw/temp*_label 2>/dev/null)" | tr ' ' '.' | tr '\n' ' ')
# extraction températures
inputT=$(gawk '$0!="" && $0!=0 {printf "%.1f/", $1/1000}' <<< $(cat /sys/class/hwmon/$ihw/temp*_input 2>/dev/null))
critT=$(gawk '$0!="" && $0!=0 {printf "%.1f/", $1/1000}' <<< $(cat /sys/class/hwmon/$ihw/temp*_crit 2>/dev/null))
hystT=$(gawk '$0!="" && $0!=0 {printf "%.1f/", $1/1000}' <<< $(cat /sys/class/hwmon/$ihw/temp*_crit_hyst 2>/dev/null))
maxiT=$(gawk '$0!="" && $0!=0 {printf "%.1f/", $1/1000}' <<< $(cat /sys/class/hwmon/$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]+' <<< $(ls /sys/class/hwmon/$ihw/) ; then
# extraction label
labelF=$(printf "%s/" $(cat /sys/class/hwmon/$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}' <<< $(cat /sys/class/hwmon/$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}
}
# assigne $fg_ip, $fg_ip_tp, $fg_gws, $fg_gws_tp, $fg_ifn_prior, $fg_ifn, $fg_mac, fg_mac_tp
figet_ip(){ # 09/11/2017
local ifn
[ $( f__which ip ) ] || return 1
fg_ip="$(sed '/[[:digit:]]:[[:blank:]]lo.*inet/d; /inet6.*scope/d' <<< $(ip -o a) | gawk '{print " ",$4,"(",$2,")"}')"
fg_ip_tp="$(sed -E 's/(^.*wl.*)/\1 (wifi)/;s/(^.*en.*|^.*eth.*)/\1 (ethernet)/' <<< $fg_ip)"
fg_gws="$(LC_ALL=C ip -4 route | gawk '/default via/ {print " ",$3,"(",$5,")"}')"
fg_gws+="$(LC_ALL=C ip -6 route | gawk '/default via/ {print " ",$3,"(",$5,")"}')"
fg_gws_tp="$(sed -E 's/(^.*wl.*)/\1 (wifi)/;s/(^.*en.*|^.*eth.*)/\1 (ethernet)/' <<< $fg_gws)"
fg_ifn_prior="$(ip route get 255.255.255.255 | sed -nr 's/.*src ([0-9.]+).*/\1/p')"
for ifn in $(ls /sys/class/net/) ; do
[ "$ifn" != "lo" ] && fg_ifn+=" $ifn"$'\n'
[ "$ifn" != "lo" ] && fg_mac+=" $ifn: $(< /sys/class/net/$ifn/address)"$'\n'
done
fg_ifn="$(sed '/^[[:blank:]]*$/d' <<< $fg_ifn)" # suppression lignes vides
fg_mac="$(sed '/^[[:blank:]]*$/d' <<< $fg_mac)" # suppression lignes vides
fg_mac_tp="$(sed -E 's/(^.*wl.*)/\1 (wifi)/;s/(^.*en.*|^.*eth.*)/\1 (ethernet)/' <<< $fg_mac)"
[ "$fg_ifn" ] && fg_ifn=${fg_ifn::-1} # suppression dernier $'\n'
[ "$fg_mac" ] && fg_mac=${fg_mac::-1} # suppression dernier $'\n'
}
# $1=4|6, assigne $fg_public
figet_ip_pub(){ # 20/11/2017
local dig_test ip_test iip
list_ip4(){
ip_test+=" http://whatismyip.akamai.com"
ip_test+=" http://ipof.in/txt"
ip_test+=" http://eth0.me"
ip_test+=" http://ipecho.net/plain"
ip_test+=" http://alma.ch/myip.cgi"
ip_test+=" http://checkip.amazonaws.com"
ip_test+=" http://eth0.me"
ip_test+=" http://ipecho.net/plain"
ip_test+=" api.infoip.io/ip" # http & https
ip_test+=" api.ipify.org" # http & https
ip_test+=" ipinfo.io/ip" # http & https
}
list_ip6(){
ip_test+=" http://ipv6.whatismyip.akamai.com"
ip_test+=" http://bot.whatismyipaddress.com"
ip_test+=" ip.tyk.nu" # http & https
ip_test+=" l2.io/ip" # http & https
ip_test+=" ident.me" # http & https
ip_test+=" icanhazip.com" # http & https
ip_test+=" wgetip.com" # http & https
ip_test+=" https://canhazip.com"
ip_test+=" https://tnx.nl/ip"
}
list_ip4_dig(){
dig_test+=" whoami.akamai.net/@ns1-1.akamaitech.net"
dig_test+=" myip.opendns.com/@resolver1.opendns.com"
dig_test+=" myip.opendns.com/@resolver2.opendns.com"
dig_test+=" myip.opendns.com/@resolver3.opendns.com"
dig_test+=" myip.opendns.com/@resolver4.opendns.com"
}
list_ip6_dig(){
dig_test+=" -6/myip.opendns.com/aaaa/@resolver1.ipv6-sandbox.opendns.com"
dig_test+=" -6/myip.opendns.com/aaaa/@resolver2.ipv6-sandbox.opendns.com"
}
unset fg_public
if [ "$1" == "4" ]; then
ping -4 -c1 google.com &>/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 google.com &>/dev/null || ping -6 -c1 free.fr &>/dev/null || return 1 # test connectivité
list_ip6_dig
list_ip6
ip_telnet=6.ifcfg.me
fi
if [ $( f__which dig ) ] && [ -z "$fg_public" ]; then
for iip in $dig_test ; do
fg_public="$(dig +short $(sed 's;/; ;g' <<< $iip))"
[ "$fg_public" ] && break
done
fi
if [ $( f__which wget ) ] && [ -z "$fg_public" ]; then
cmd="wget --quiet --timeout=5 -O - "
for iip in $ip_test ; do
fg_public="$($cmd $iip)"
[ "$fg_public" ] && break
done
fi
if [ $( f__which curl ) ] && [ -z "$fg_public" ]; then
cmd="curl --silent --location --retry 0 --max-time 5" #--location pour aider redirections
for iip in $ip_test ; do
fg_public="$($cmd $iip)"
[ "$fg_public" ] && break
done
fi
if [ $( f__which telnet ) ] && [ -z "$fg_public" ]; then
fg_public="$(telnet $ip_telnet 23 2>/dev/null | grep $1 | cut -d ' ' -f 4)"
fi
if [ $( f__which nc ) ] && [ -z "$fg_public" ] && [ "$1" != "IPv6" ]; then
fg_public="$(nc $ip_telnet 23 2>/dev/null | grep $1 | cut -d ' ' -f 4)"
fi
if [ -z "$fg_public" ]; 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\n" \
"si l'erreur persiste, merci de prévenir $projet, $contact"
fi
}
# $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(){ # 27/11/2017
local freeDebug MemTotal MemFree MemAvailable Buffers Cached SReclaimable Shmem MemUsed
local SwapTotal SwapFree SwapCached col a b
[ "$2" == "debug" ] && freeDebug="$(free -hw | sed '3d')"
IFS=':'
while read a b; do
[ "$a" == "MemTotal" ] && MemTotal="${b/kB}" #echo "$a $((${b/kB}/1024))" ! partie entière !
[ "$a" == "MemAvailable" ] && MemAvailable="${b/kB}"
[ "$a" == "MemFree" ] && MemFree="${b/kB}"
[ "$a" == "Buffers" ] && Buffers="${b/kB}"
[ "$a" == "Cached" ] && Cached="${b/kB}"
[ "$a" == "SReclaimable" ] && SReclaimable="${b/kB}"
[[ "$a" =~ Shmem$|MemShared$ ]] && Shmem="${b/kB}" # = free shared
[ "$a" == "SwapTotal" ] && SwapTotal="${b/kB}"
[ "$a" == "SwapFree" ] && SwapFree="${b/kB}"
[ "$a" == "SwapCached" ] && SwapCached="${b/kB}"
done <<< $(< /proc/meminfo)
$IFS="$IFS_INI"
MemUsed=$(( $MemTotal-($MemFree+$Buffers+$Cached+$SReclaimable) ))
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'
}
# assigne $fg_mod_net # 30/10/2017
figet_mod_net(){ # thanks wireless-info
local MODMATCHES LSMODMATCHES
MODMATCHES="(air|ar5|at7|ath[^3]?|b43|bcma|brcm|carl|ipw|iwl|ndis|r(818|8192[eu]|871|92su)|8(188|189|192|723|812)[acde][esu]|rt[23567]|rtl|ssb|wl|(cfg|mac)80211)"
LSMODMATCHES="(wmi|(dell|ideapad)[-_]laptop)"
fg_mod_net="$(lsmod | grep -E "(^|[[:punct:] ])($MODMATCHES|$LSMODMATCHES)[^[:punct:] ]*([[:punct:] ]|$)")"
}
# assigne $fg_nb_screen, $fg_resolution. return fg_resolution=n/a[ (ssh)] & fg_nb_screen=n/a ou valeurs
figet_screen(){ #v2 25/11/2017
fg_nb_screen="n/a"
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 25/11/2017 # thanks neofetch
local shell ish
# 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
}
figet_test_batt(){ # 20/11/2017
local text var_temp objet
# matériel
figet_dmi
figet_batt
###
f_display "fg_dmi" "sans"
text="--- \n\n"
text+="## batterie test \n\n"
# acpi éventuel
if [ $( f__which acpi ) ]; then
var_temp=$(acpi -abi)
[ "$var_temp" ] || var_temp="pas de batterie dans $( f__which acpi )"
f_display "var_temp" "cmd" "acpi -abi"
fi
# upower
if [ $( f__which upower ) ]; then
objet=$(grep -i 'battery' <<< $(upower -e))
var_temp=$(upower -i $objet)
f_display "var_temp" "cmd" "upower -i $objet"
fi
# scandir
[ -d /sys/class/power_supply/BAT* ] && f_dspl_scandir "/sys/class/power_supply/" 1
# fonction script
f_display "fg_batt" "var" "figet_batt"
}
figet_test_distrib(){ # 29/10/2017
local etc lsb
etc=$(grep -Hs . /etc/*release /etc/*version)
lsb=$(lsb_release -a 2>/dev/null)
###
figet_dmi
f_display "fg_dmi" "var" "distrib test"
f_display "etc" "cmd" "grep -Hs . /etc/*release /etc/*version"
f_display "lsb" "cmd" "lsb_release -a"
figet_distrib
f_display "fg_distrib" "var" "fg_distrib"
}
figet_test_dmi(){ # 21/10/2017
local text var_temp
text+="## dmi test \n\n"
# /sys/class/dmi/
var_temp="/sys/class/dmi/"
f_dspl_scandir "$var_temp" 1
# fonction script
figet_dmi
f_display "fg_dmi" "var" "figet_dmi"
}
figet_test_gpu(){ # 30/10/2017
local lspci="$(lspci -mm)"
figet_dmi
f_display "fg_dmi" "var" "gpu test"
f_display "lspci" "cmd" "lspci -mm"
figet_gpu
f_display "fg_gpu" "var" "fg_gpu"
}
figet_test_hw(){ # 25/11/2017
local text var_temp
# matériel
figet_dmi
f_display "fg_dmi" "sans"
text="--- \n\n"
###
text+="## hwmon test \n\n"
# sensors et acpi éventuel
if [ $( f__which sensors ) ]; then
var_temp=$(sensors -u)
f_display "var_temp" "cmd" "sensors -u"
fi
if [ $( f__which acpi ) ]; then
var_temp=$(acpi -V | grep -E 'Thermal|Cooling')
f_display "var_temp" "cmd" "acpi -V"
fi
# /sys/class/hwmon/
var_temp="/sys/class/hwmon/"
f_dspl_scandir "$var_temp" 1
# /sys/class/thermal/thermal_zone0/
var_temp="/sys/class/thermal/thermal_zone0/"
f_dspl_scandir "$var_temp" 0
# /sys/devices/platform/coretemp.0/hwmon/
var_temp="/sys/devices/platform/coretemp.0/hwmon/"
f_dspl_scandir "$var_temp" 1
# analyse méthode neofetch
if [ -e "/sys/class/hwmon/hwmon0/temp1_input" ]; then
var_temp="$(< "/sys/class/hwmon/hwmon0/temp1_input")"
var_temp="$((var_temp * 100 / 10000))" # 33000 x 100 / 10 000 = 330
var_temp="[${var_temp/${var_temp: -1}}.${var_temp: -1}°C]" # formatage 1 point décimal
else
var_temp=" non accessible"
fi
f_display "var_temp" "var" "hwmon0/temp1_input à là neofetch"
# fonction script
[ "$fg_hw" ] || figet_hw
f_display "fg_hw" "var" "figet_hw"
}
# debian indépendant, assigne $fg_ucode (commentaire), $ucode (paquet deb) & return O|1 (1 si pas d'installation)
figet_ucode(){ # 24/11/2017
local flagRep xfile xfileTest=""
# recherche flags cpu rep_good (besoin réel?)
[ "$( grep -cm1 'flags.*rep_good ' /proc/cpuinfo )" -ge 1 ] && flagRep="rep_good ⟷ rep microcode works well"
# flags architecture processeur, à priori pas utile
# test possible installation
[ "$fg_cpu" ] || figet_cpu
[ "${fg_vendor,,}" == "amd" ] && ucode="amd64-microcode"
[ "${fg_vendor,,}" == "intel" ] && ucode="intel-microcode"
# version debian, à supprimer à terme après essai sur autre distrib
# if [ "$ENV_DEB" ]; then # debian ?
# f__requis "$ucode" "debOnly"
# [ "$debOnlyAbsent" == "$ucode" ] && return 1 || return 0
# fi
# 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 possible"
[ "$flagRep" ] && fg_ucode+=", flag Cpu: $flagRep"
return 1
elif [[ ${#xfileTest} -eq 0 && -z "$ucode" ]]; then # non installé, non possible
[ "$flagRep" ] && fg_ucode="pas de microcode possible, mais flag Cpu: $flagRep" # pas de commentaire sauf si flag
return 0
elif [[ ${#xfileTest} -gt 0 && "$ucode" ]]; then # installé, possible, installé
fg_ucode="microcode installé"
[ "$flagRep" ] && fg_ucode+=", flag Cpu: $flagRep" || fg_ucode+=", mais 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
figet_wm(){ #v 25/11/2017 thanks neofetch
local id wm_brut compositor
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 ...
##
id=$( xprop -root -notype _NET_SUPPORTING_WM_CHECK )
id=${id##* } # suppression plus grande chaîne au début jusqu"à ' '
wm_brut=$( xprop -id "$id" -notype -len 100 -f _NET_WM_NAME 8t )
[ "$debug" ] && echo -e "\n$wm_brut\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' )
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 # en aveugle, jamais vu d'essai
compositor=${wm_brut/*muffin_version = } # suppression jusqu'à ...
compositor=${compositor/\"} # suppression premier"
compositor=${compositor/\"*} # suppression 2e " avec éventuels caractères suivants
compositor="(Muffin v$compositor)"
fi
if [[ "$wm_brut" =~ marco_version ]]; then
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)}
fi
[ "$compositor" ] && fg_wm="$fg_wm $compositor"
fg_wm=${fg_wm^} # caractère 1 en majuscule
}
# 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(){ # 06/11/2017
local dirAnacron dirSpool fileAnacron
[ "$(type -t fscript_cronAnacron_special)" ] && fscript_cronAnacron_special # test, si fonction spécifique, appel
dirAnacron="/home/$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 $fileInstall --upgrade 1>/dev/null" > "$fileAnacron" # juste erreurs en syslog
## anacron journalier pour dev logname
if [ -e "$fileDev" ]; then
echo "1 00 $script""Dev nice $fileInstall --upgrade 1>/dev/null" >> "$fileAnacron"
fi
# création spool anacron utilisateur
mkdir -p "$dirSpool"
chown -R "$user_:" "$dirAnacron" "$dirSpool"
if [ "$EUID" -eq 0 ]; then
# crontab pour activation horaire anacron
echo "@hourly $user_ /usr/sbin/anacron -t $fileAnacron -S $dirSpool" >> /etc/crontab
fi
[ "$(grep "$script" /etc/crontab)" ] || echo f__error "inscription crontab" \
"certains systèmes semblent poser poser problème, merci de rapporter ce bug à $projet, $contact"
;;
remove )
rm "$dirSpool/$script"* &>/dev/null
rm "$fileAnacron" &>/dev/null
rmdir "$dirSpool" "$dirAnacron" &>/dev/null
;;
esac
}
# version script en ligne, [$1=update], assigne $versionScript, $script_aJour=ok|ko
fscript_get_version(){ # 06/11/2017
local var_temp
f__info "raw" "$GREEN""version script en cours: $version"
versionScript=$(wget -q --timeout=15 -O - "$urlScript" | grep -m1 '^version=' | cut -d'=' -f2)
if [ "$versionScript" ]; then
if [ "$version" != "$versionScript" ]; then
[ "$1" = "update" ] && var_temp=", mise à jour en cours"
[ "$1" = "update" ] || var_temp=", mise à jour possible"
script_aJour="ko"
else
script_aJour="ok"
fi
f__info "version script en ligne: $versionScript$var_temp"
else
f__info "version script en ligne$RED non accessible"
fi
}
# installation du script dans le système
fscript_install(){ # 10/11/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 "$(basename $0)" "$fileInstall"
ln -s "$fileInstall" "/usr/bin/$script" &>/dev/null
chmod 775 "$fileInstall" # rwx rwx r-x, proprio user_
# cron/anacron install
fscript_cronAnacron "install"
# création fichier log
touch "$fileLogs"
chmod 664 "$fileLogs" # rw- rw- r--, proprio user_
chown "$user_:" "$fileLogs" "$fileInstall"
[ -e "$fileDev" ] || rm "$(basename $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(){ # 06/11/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 "$fileInstall" ];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
rm "$fileInstall" &>/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 si dispo, v2, +update spécifique
fscript_update(){ # 06/11/2017
local dirTemp="/tmp/$script-$RANDOM"
[ $(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
fscript_get_version "update"
if [ "$script_aJour" == "ok" ]; then
f__info "log" "pas de mise à jour disponible pour $script $version"
return 0
fi
mkdir -p "$dirTemp"
wget -q --tries=2 --timeout=15 -O "$dirTemp/$script" "$urlScript"
if [ "$?" != "0" ]; then f__wget_test "$urlScript"; fi
if grep -q '#!/bin/bash' "$dirTemp/$script" ; then
cp -d "$dirTemp/$script" "$fileInstall"
chmod 775 "$fileInstall" # rwx rwx r-x, proprio user_
chown "$user_:" "$fileInstall"
[ -z "$updateSpecial" ] && fscript_cronAnacron "upgrade"
f__info "log" "$script mis à jour en version $versionScript $updateSpecial"
else
rm -rf "$dirTemp/"
f__error "échec update" "mauvais téléchargement, réessayer plus tard"
fi
rm -rf "$dirTemp/"
}
prg_init(){ # 25/11/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
[ -e /proc/cpuinfo ] || f__error "/proc/cpuinfo non trouvé" "/proc ne doit pas être monté"
# 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"
# 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 ] && user_="root" || f__error "user détecté, mais pas de home: /home/$user_"
f__info "user root"
fi
# requis pour fonctionnement programme
f__requis "gawk wget ip>iproute2 lspci>pciutils wc>coreutils" || exit 1
# detect rapide systeme deb pour f_requis debOnly, en attendant mieux
[ $( f__which dpkg ) ] && ENV_DEB="oui"
}
prg_1(){ # début
echo > "$fileOutput"
chown $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\n" >> "$fileOutput"
}
prg_2(){ # traitements principaux 21/11/2017
if [[ "$1" == all || "$1" =~ s ]]; then #systeme, matériel -cs
echo -e "# ▷ Système \n\n" >> "$fileOutput"
for i in fi_systeme fi_cpu fi_mem fi_hw fi_batt fi_graph fi_disk fi_usb ; do
echo -n "•"
$i
done
fi
if [[ "$1" == all || "$1" =~ c ]]; then #configuration #debian, packages -cc fi_conf
echo -e "# ▷ Configuration \n\n" >> "$fileOutput"
for i in 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 \n\n" >> "$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 \n\n" >> "$fileOutput"
for i in fi_efi fi_system_analyse fi_log_xorg fi_journal ; do
echo -n "•"
$i
done
fi
}
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 l'exporter ultérieurement avec $BLUE$script -p"
}
prg_menu(){ # 10/10/2017
function display_menu {
local centre=50 left=2 larg=60 reply line
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"
}
printf " $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"
printf "\n choix des catégories à générer (all pour toutes)? "
tput sc
printf "\n ( ne pas saisir le préfixe $YELLOW-c$STD, all par défaut)"
tput rc
read reply
[ "$reply" ] && reply="-c${reply,,}" || reply="all"
reply="$(sed 's/-call/all/' <<< $reply)"
exec $0 "$reply"
}
######## début script / initialisation
# logo et définition couleurs
f__affichage
# tests au démarrage
prg_init
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
fileOutput="getInfo_rapport.md"
fileLogs="/var/log/sdeb_$script.log"
fileDev="/opt/bin/fileDev"
fileInstall="/opt/bin/$script"
urlScript="https://frama.link/getInfo"
urlNotice="https://frama.link/doc-getInfo"
# test sur frama.link ok, sinon fallback sur framagit
if [[ "$options" =~ all|-d|-h|-c|-v ]]; then
if ! f__wget_test "$urlScript" "test"; then
urlScript="https://framagit.org/kyodev/kyopages/raw/master/scripts/$script"
urlNotice="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]($urlNotice)"
# 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 )
prg_1 "$*"
echo -n "•"
fi_disk
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
-j )
prg_1 "$*"
prg_2 "a"
exit ;; # exporte le rapport existant
-l )
f_dspl_md "$fileOutput"
exit ;; # afficher le rapport existant
-p )
fipaste
exit ;; # exporte le rapport existant
-h )
f_help
exit ;; # affichage help
--debug-all )
prg_1 "$*"
figet_test_batt
figet_test_distrib
figet_test_dmi
figet_test_gpu
figet_test_hw
prg_3
exit ;; # test batterie, dmi, hwmon
--debug-batt )
prg_1 "$*"
figet_test_batt
prg_3
exit ;; # test batterie avec scan /sys/class/power_supply/
--debug-dist )
prg_1 "$*"
figet_test_distrib
prg_3
exit ;; # test distrib
--debug-dmi )
prg_1 "$*"
figet_test_dmi
prg_3
exit ;; # test dmi avec affichage /sys/class/dmi/id/
--debug-gpu )
prg_1 "$*"
figet_test_gpu
prg_3
exit ;; # test gpu
--debug-hw )
prg_1 "$*"
figet_test_hw
prg_3
exit ;; # test hwmon avec affichage /sys/class/hwmon/
--ip )
if figet_ip_pub "4" ; then
f__info "raw" " ipv4 publique: $GREEN$fg_public"
else
f__info "$BLUE pas de connectivité ipv4"
fi
if figet_ip_pub "6" ; then
f__info "raw" " ipv6 publique: $GREEN$fg_public"
else
f__info "$BLUE pas de connectivité ipv6"
fi
exit ;; # affiche ip public
--mac )
figet_ip
f__info "fg_mac:\n$GREEN$fg_mac_tp"
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"
fileInstall="$(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
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
### END CONTROL (contrôle chargement)