| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113 |
- #!/bin/bash
- # Auteur : Remi Sarrailh (maditnerd)
- # Updates : Modifications mineures par Valentin CARRUESCO Idleman 28/07/2018
- # Licence : MIT
- # Un probleme : https://git.idleman.fr/idleman/yana-server/issues
- # https://tldrlegal.com/license/mit-license
- #############
- # Variables
- #############
- INSTALLVERSION="3.0.6"
- ERR="\033[1;31m"
- NORMAL="\033[0;39m"
- INFO="\033[1;34m"
- WARN="\033[1;33m"
- OK="\033[1;32m"
- IPADDRESS=$(hostname -I)
- HOSTNAME=$(cat /etc/hostname)
- doInstall=0
- #Installer le serveur web (se met à 0 si un autre serveur web est installé)
- doInstallWebServer=1
- isRoot=0
- GlobalError=0
- confirmErase=0
- copyYana=1
- resizeSD=1
- ################
- # Messages GUI
- ################
- # J'ai séparé les messages long du GUI du reste du programme
- # Afin quel soit facilement modifiable
- installMessage="\
- Etapes:
- ---------------------------
- * Renommer le Raspberry Pi
- * Redimensionner la carte SD
- * Mis à jour
- * Terminal en français
- ------------------------------------
- * Configuration du fuseau horaire
- * Installation wiringPi (pour gérer les GPIO)
- -------------------------------------------
- * Copie de Yana Server
- * Installation du serveur web
- * Création de l'utilisateur
- * Permissions du serveur web
- * Installation du socket / cron
- "
- checkMessage="\
- Nous allons revérifier toute l'installation mais sans modifier ni yana-server ni la configuration
- "
- renameMessage="\
- Vous pouvez accéder à Yana en utilisant un nom plutôt qu'une adresse IP \n\n\
- Pour que cela marche depuis Windows, il faut que les services BONJOUR soit installés \n\
- C'est le cas si vous avez SKYPE, ITUNES ou Windows 10 sinon il vous faudra l'installer \n\
- http://support.apple.com/kb/DL999 \n\
- \n\
- \n\
- Example : maison sera accessible sur http://maison.local/
- "
- saveMessage="\
- Vous pouvez sauvegarder yana-server sur une clé USB \n\n\
- Ceci sauvegardera /var/www/yana-server dans le dossier yana \n\n\
- Si une sauvegarde existe sur la clé, elle sera effacée \n\
- si vous voulez conserver une sauvegarde précédente renommer le dossier \n\
- "
- restoreMessage="\
- Vous pouvez revenir à un état précédent de yana depuis une clé USB \n\n\
- Ceci effacera /var/www/yana-server et le replacera par celui \n\
- dans le dossier sur la clé USB /yana
- "
- resizeSDCardMessage="\
- Voulez vous redimensionner la carte SD de votre Raspberry Pi ?
- Ceci sera fait au prochain redémarrage.
- "
- # Message d'erreurs
- noInternetMessage="\
- Je n'arrive pas à me connecter à git.idleman.fr \n\
- Voici votre adresse IP: $IPADDRESS\
- "
- ApacheMessage="\
- Yana utilise lighttpd comme serveur web par défaut\n\
- Il semblerait que Apache (un autre serveur web) soit déjà installé...\n\n\
- Voulez vous quand même installer lighttpd ? \n\
- "
- nginxMessage="\
- Yana utilise lighttpd comme serveur web par défaut\n\
- Il semblerait que nginx (un autre serveur web) soit déjà installé...\n\n\
- Voulez vous quand même installer lighttpd ? \n\
- "
- yanaMessage="\
- Yana semble avoir déjà été copié.\n\
- Voulez vous que je le supprimer et que je le réinstalle ?\
- "
- localeMessage="\
- Je n'ai pas réussi à mettre le terminal en français\n\
- Pour autant, ceci n'aura aucune incidence sur la suite de l'installation\n\n\
- Voici le message d'erreur:\
- "
- aptGetErrorMessage="\
- Le gestionnaire de paquet apt-get est HS\n\
- * Soit celui-ci a été interrompu\n\
- * Soit il est en cours d'utilisation par un autre programme\n\
- Supprimer le fichier de verrou est probablement la solution\n\n\
- Voici le message d'erreur:\n\
- "
- gitErrorMessage="\
- Impossible de récupérer le code source avec git\n\
- Cela peut être du à un problème du coté de git.idleman.fr\n\
- Veuillez vérifier que http://git.idleman.fr/ est en ligne\n\n\
- Voici le message d'erreur:\n\
- "
- wiringPiErrorMessage="\
- Impossible de compiler wiringPi\n\
- Voici le message d'erreur:\n\
- "
- lighttpdErrorMessage="\
- Le serveur web n'a pas réussi à se redémarrer correctement\n\
- Voici le message d'erreur:\n\
- "
- #Un joli logo ascii sans avoir à installer un programme pour ça
- yanaLogo(){
- clear
- echo -ne $INFO
- cat<<EOF
- ██╗ ██╗ █████╗ ███╗ ██╗ █████╗ ████████╗
- ╚██╗ ██╔╝██╔══██╗████╗ ██║██╔══██╗ █ █ █ █║
- ╚████╔╝ ███████║██╔██╗ ██║███████║ █ █║
- ╚██╔╝ ██╔══██║██║╚██╗██║██╔══██║ ██████ ║
- ██║ ██║ ██║██║ ╚████║██║ ██║ █ ████ █║
- ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ █ █══╝
- EOF
- echo -ne $ERR
- cat<<EOF
- ██╗███╗ ██╗███████╗████████╗ █████╗ ██╗ ██╗
- ██║████╗ ██║██╔════╝╚══██╔══╝██╔══██╗██║ ██║
- ██║██╔██╗ ██║███████╗ ██║ ███████║██║ ██║
- ██║██║╚██╗██║╚════██║ ██║ ██╔══██║██║ ██║
- ██║██║ ╚████║███████║ ██║ ██║ ██║███████╗███████╗
- ╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝
- EOF
- echo -ne $NORMAL
- }
- ##############
- # Menus
- ##############
- # Menu principal
- mainMenu(){
- optionsMain=$(whiptail --title "YANA Server $INSTALLVERSION" --menu "" --cancel-button "Annuler" 0 0 0 \
- "Installer" "" \
- "Configurer" "" \
- "Sauvegarder" "" \
- "Restaurer" "" \
- "Quitter" "" 3>&1 1>&2 2>&3)
- case $optionsMain in
- "Installer")
- installMenu;;
- "Configurer")
- setupMenu;;
- "Sauvegarder")
- saveMenu;;
- "Restaurer")
- restoreMenu;;
- *)
- echo -e "$OK ... A la prochaine! $NORMAL"
- ;;
- esac
- }
- # Menu d'installation
- installMenu(){
- if(whiptail --title "Installation" --yesno "$installMessage" --yes-button "Oui" --no-button "Non" 0 0) then
- doInstall=1
- else
- echo -e "\033[1;34m... A la prochaine!\033[0;39m"
- fi
- }
- # Menu de configuration
- setupMenu(){
- optionsSetup=$(whiptail --title "YANA Server $INSTALLVERSION" --menu "" --cancel-button "Retour" 0 0 0 \
- "Vérifier YANA" "" \
- "Mettre à jour YANA" "" \
- "Redimensionner la carte SD" "" \
- "Renommer le Raspberry Pi" "" \
- "Scripts Plugins" "" \
- "Quitter" "" \
- 3>&1 1>&2 2>&3)
- case $optionsSetup in
- "Vérifier YANA")
- checkMenu;;
- "Mettre à jour YANA")
- forceYanaUpdate;;
- "Redimensionner la carte SD")
- resizeSDCard
- setupMenu;;
- "Renommer le Raspberry Pi")
- renameMenu
- setupMenu;;
- "Scripts Plugins")
- scriptsMenu;;
- "Quitter")
- echo -e "$OK ... A la prochaine! $NORMAL";;
- *)
- mainMenu;;
- esac
- }
- # Menu vérification de yana
- checkMenu(){
- if(whiptail --title "Vérification" --yesno "$checkMessage" --yes-button "Oui" --no-button "Non" 0 0) then
- updateRaspberryPi
- checkPermissions
- checkBinariesMenu
- installYanaSocket
- addCron
- else
- setupMenu
- fi
- }
- resizeSDCardMenu(){
- if(whiptail --title "Carte SD" --yesno "$resizeSDCardMessage" --yes-button "Oui" --no-button "Non" 0 0) then
- resizeSDCard
- fi
- }
- # Menu de renommage du Raspberry Pi
- renameMenu(){
- newhostname=$(whiptail --inputbox "$renameMessage" --title "Choissisez un nom" 0 0 3>&1 1>&2 2>&3)
- renamePi
- }
- # Menu de scripts pour les plugins
- # Il faut créer un script au format .sh pour dans /var/www/yana-server/plugins/nom-du-plugin/nom-du-script.sh
- # On peut utiliser les fonctions du script d'installation et les variables à l'intérieur d'un script
- # Par example vous pouvez récupérer le nom $HOSTNAME ou l'adresse IP $IPADDRESS
- # Vérifier si internet est connecté
- scriptsMenu(){
- getAllScripts
- while read -r nextScript
- do
- scriptName=$(echo "${nextScript//\/var\/www\/yana-server\/plugins\//}")
- menu_options[ $i ]="$scriptName"
- (( i++ ))
-
- menu_options[ $i ]=""
- (( i++ ))
- done <<<"$allScripts"
- scriptToExecute=$(whiptail --title "Plugins" --menu "Gérer un Plugin" 0 0 0 "${menu_options[@]}" 3>&1 1>&2 2>&3 )
- executeScript
- }
- executeScript(){
- if [[ -f /var/www/yana-server/plugins/$scriptToExecute ]];then
- chmod +x /var/www/yana-server/plugins/$scriptToExecute
- clear
- yanaLogo
- echo -e "$OK -----> Exécution de $scriptToExecute $NORMAL"
- dir=$(dirname /var/www/yana-server/plugins/$scriptToExecute)
- cd $dir;. /var/www/yana-server/plugins/$scriptToExecute
- else
- echo -e "$OK -----> Aucun script trouvé dans /var/www/yana-server/plugins/$scriptToExecute $NORMAL"
- fi
- }
- # Menu de vérification des fichiers binaires
- checkBinariesMenu(){
- getAllBinaries
- if(whiptail --title "Permissions binaires" --yesno "Je peux automatiquement donner les droits roots aux programmes des plugins\n\nVoici la liste des programmes concernés: \n$allBinaries" --yes-button "Oui" --no-button "Non" 0 0) then
- setupPermissionsBinaries
- whiptail --title "Permissions" --msgbox "Permissions activés" 0 0
- fi
- }
- saveMenu(){
- if(whiptail --title "Sauvegarde USB" --yesno "$saveMessage" --yes-button "Oui" --no-button "Non" 0 0) then
- saveUSB
- else
- mainMenu
- fi
- }
- restoreMenu(){
- if(whiptail --title "Restauration USB" --yesno "$restoreMessage" --yes-button "Oui" --no-button "Non" 0 0) then
- restoreUSB
- checkPermissions
- setupPermissionsBinaries
- else
- mainMenu
- fi
- }
- ## Menu d'erreurs
- # Menu Internet HS
- noInternetMenu(){
- whiptail --title "Vérifier que vous êtes connecté à internet" --msgbox "$noInternetMessage" 0 0
- echo -e "$ERR - Impossible de continuer sans internet $NORMAL"
- }
- # Menu Apache déjà installé
- ApacheAlreadyInstalledMenu(){
- if(whiptail --title "Un serveur web est déjà installé" --yesno "$ApacheMessage" --yes-button "Oui" --no-button "Non" 0 0) then
- doInstallWebServer=1
- else
- doInstallWebServer=0
- fi
- }
- # Menu Nginx déjà installé
- nginxAlreadyInstalledMenu(){
- if(whiptail --title "Un serveur web est déjà installé" --yesno "$nginxMessage" --yes-button "Oui" --no-button "Non" 0 0) then
- doInstallWebServer=1
- else
- doInstallWebServer=0
- fi
- }
- # Menu error APT-GET
- aptgetErrorMenu(){
- #Récupère le message d'erreur apt-get
- getAptError
- #Affiche l'erreur dans la GUI
- whiptail --title "le gestionnaire de paquet ne réponds pas" --msgbox "$aptGetErrorMessage $aptError" 0 0
- echo -e "$ERR Impossible de continuer sans apt-get $NORMAL"
- echo -e "$WARN ERREUR - $aptGetErrorMessage $aptError"
- exit 1
- }
- # Menu erreur git
- gitErrorMenu(){
- #Récupère le message d'erreur de git clone
- getGitError
- #Affiche l'erreur dans la GUI
- whiptail --title "le gestionnaire de paquet ne réponds pas" --msgbox "$gitErrorMessage $gitError" 0 0
- exit 1
- }
- # Menu erreur wiringPi
- wiringPiErrorMenu(){
- getWiringPiError
- whiptail --title "Echec de la compilation de WiringPi" --msgbox "$wiringPiErrorMessage $wiringPiError" 0 0
- }
- # Menu erreur lighttpd
- lighttpdErrorMenu(){
- whiptail --title "Echec du lancement de Lighttpd" --msgbox "$lighttpdErrorMessage $lighttpdError" 0 0
- }
- confirmEraseUSB(){
- if(whiptail --title "Confirmer la suppression de la sauvegarde" --yesno "Une sauvegarde précédente existe la supprimer ?" --yes-button "Oui" --no-button "Non" 0 0) then
- confirmErase=1
- else
- confirmErase=0
- fi
- }
- ##############
- # Scripts
- ##############
- # Toutes les parties de l'installation sont séparés en fonctions
- # Ceci afin de faciliter les tests de chaque partie
- #Vérifie que vous êtes bien en root
- verifyRoot() {
- if [ $(id -u) -ne 0 ]; then
- echo -e "\033[1;31mVous avez oublié de vous mettre en root!\033[0;39m"
- echo -e "Tapez \033[1;34msudo $0\033[0;39m"
- isRoot=0
- else
- isRoot=1
- fi
- }
- #Vérifie l'état de la connexion internet
- checkInternet(){
- ping -c1 www.google.com > /dev/null 2>&1 && internet=1 || internet=0
- echo -e "$OK -----> Vérification de la connexion à internet $NORMAL"
- if [[ $internet -eq 0 ]]
- then
- noInternetMenu
- fi
- }
- #Récupère le message d'erreur APT-GET
- getAptError(){
- rm -f /tmp/aptError.log
- #On lance apt-get install en dry-run (simulation) afin de recuperer l'erreur
- #et on sauve le log dans /tmp/aptError.log
- apt-get --dry-run install > /tmp/aptError.log 2>&1
- aptError=$(cat /tmp/aptError.log)
- }
- #Récupère le message d'erreur de git
- getGitError(){
- gitError=$(cat /tmp/gitError.log)
- }
- #Récupère le message d'erreur de WiringPi
- getWiringPiError(){
- wiringPiError=$(cat /tmp/wiringPiError.log)
- }
- #Récupère le message d'erreur de lighttpd
- getLighttpdError(){
- lighttpdError=$(cat /tmp/lighttpdReload.log)
- }
- #Met à jour le Raspberry Pi en utilisant whiptail comme interface
- updateRaspberryPi(){
- echo -e "$OK -----> Mise à jour du Raspberry Pi $NORMAL"
- #debconf-apt-progress permet d'afficher la progression de la mis à jour dans une GUI en français
- debconf-apt-progress -- apt-get -q -y update
- globalError=$?
- if [[ $globalError -ne 0 ]];then
- aptgetErrorMenu
- fi
- debconf-apt-progress -- apt-get -q -y upgrade
- globalError=$?
- if [[ $globalError -ne 0 ]];then
- aptgetErrorMenu
- fi
- echo -e "$OK -----> Installation du client git $NORMAL"
- #On installe aussi le client git
- debconf-apt-progress -- apt-get install -q -y git-core
- if [[ $globalError -ne 0 ]];then
- aptgetErrorMenu
- fi
- }
- #Change les locales de l'anglais au français de manière non interactive
- setLocaleToFrench(){
- echo -e "$OK -----> Configuration du terminal en français... Patientez s'il vous plaît ... $NORMAL"
- #Ajout des locales FR
- sed -i -e 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/' /etc/locale.gen
- #Met FR en locale par défaut
- echo 'LANG="fr_FR.UTF-8 UTF-8"'>/etc/default/locale
- update-locale LANG=fr_FR.UTF-8
- export LANG=fr_FR.UTF-8
- #Les locales sont installés silencieusement
- dpkg-reconfigure --frontend=noninteractive locales > /tmp/localeSetup.log 2>&1
- globalError=$?
- #En cas d'erreur on affiche le message
- if [[ $globalError -ne 0 ]];then
- localeError=$(cat /tmp/localeSetup.log)
- whiptail --title "Locales FR" --msgbox "$localeMessage $localeError" 0 0
- fi
- }
- #Gestion automatique des fuseaux horaires à l'aide de tzupdate
- configureTimeZone(){
- echo -ne "$OK -----> Configuration du fuseau horaire $NORMAL"
- #Vérifie que Python PIP est disponible
- debconf-apt-progress -- apt-get install -q -y python-pip
- globalError=$?
- if [[ $globalError -ne 0 ]];then
- aptgetErrorMenu
- fi
- #Installation silencieuse du Package python tzupdate
- pip install --quiet tzupdate
- #Si l'installation c'est correctement passé lancé tzupdate silencieusement
- if [ -f /usr/local/bin/tzupdate ];then
- tzupdate > /dev/null 2>&1
- #On récupère après la zone géographique pour l'afficher
- currentTimeZone=$(tzupdate -p|awk '{print $4}')
- echo -e "$WARN : $currentTimeZone $NORMAL"
- else
- echo -e "$ERR Impossible de changer le fuseau horaire automatiquement (ce n'est pas nécessaire) $NORMAL"
- fi
- }
- #Vérification sommaire de l'existance d'autres serveur web
- #Si un autre serveur web est installé prévient l'utilisateur
- #Afin qu'il choissisent s'il veut installer lighttpd ou pas
- checkWebServer(){
- if [ -f "/usr/sbin/apache2" ];then
- ApacheAlreadyInstalledMenu
- fi
- if [ -f "/usr/sbin/nginx" ];then
- nginxAlreadyInstalledMenu
- fi
- }
- #Installation du serveur web et de SQLite
- installWebServer(){
- echo -e "$OK -----> Installation du serveur web $NORMAL"
- debconf-apt-progress -- apt-get install -q -y lighttpd git-core sqlite3 php7.0-sqlite php7.0-common php7.0-cgi php7.0-cli php-mbstring php7.0-zip
- if [[ $globalError -ne 0 ]];then
- aptgetErrorMenu
- fi
- #On efface la page par défaut de lighttpd pour éviter d'embrouiller les utilisateurs
- rm -f /var/www/index.lighttpd.html
- rm -rf /var/www/html
- }
- #Configure lighttpd pour bloquer l'accès à la base de données
- setupWebServer(){
- echo -e "$OK -----> Configuration du serveur web (/etc/lighttpd/lighttpd.conf) $NORMAL"
- cat <<\EOF > /etc/lighttpd/lighttpd.conf
- server.modules = (
- "mod_access",
- "mod_alias",
- "mod_compress",
- "mod_redirect",
- # "mod_rewrite",
- )
- server.document-root = "/var/www/"
- server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
- server.errorlog = "/var/log/lighttpd/error.log"
- server.pid-file = "/var/run/lighttpd.pid"
- server.username = "www-data"
- server.groupname = "www-data"
- server.port = 80
- index-file.names = ( "index.php", "index.html", "index.lighttpd.html" )
- url.access-deny = ( "~", ".inc", "db","log.txt" )
- static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
- compress.cache-dir = "/var/cache/lighttpd/compress/"
- compress.filetype = ( "application/javascript", "text/css", "text/html ) ", "text/plain" )
- # default listening port for IPv6 falls back to the IPv4 port
- include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
- include_shell "/usr/share/lighttpd/create-mime.assign.pl"
- include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
- EOF
- lighttpdSetupError=$?
- if [[ lighttpdSetupError -eq 1 ]];then
- echo -e "$ERR - Le fichier /etc/lighttpd/lighttpd.conf n'a pas été modifié $NORMAL"
- fi
- #Activation de PHP et rechargement de lighttpd
- lighty-enable-mod fastcgi-php > /dev/null 2>&1
- service lighttpd restart > /tmp/lighttpdReload.log 2>&1
- globalError=$?
- if [[ $globalError -ne 0 ]];then
- getLighttpdError
- lighttpdErrorMenu
- echo -e "$ERR - La configuration de /etc/lighttpd/lighttpd.conf a échoué $NORMAL"
- echo -e "$WARN ERREUR: $lighttpdError $NORMAL"
- fi
- }
- #Clonage de Yana
- #Si Yana a déjà été cloné alors on propose à l'utilisateur de le réinstaller
- cloneYana(){
- if [[ copyYana -eq 1 ]];then
- if [[ -d "/var/www/yana-server" ]];then
- if(whiptail --title "Yana déjà installé" --yesno "$yanaMessage" --yes-button "Oui" --no-button "Non" 0 0) then
- echo -e "$ERR -----> Réinstallation de Yana Server $NORMAL"
- rm -rf /var/www/yana-server
- GIT_SSL_NO_VERIFY=true git clone https://git.idleman.fr/idleman/yana-server.git /var/www/yana-server > /tmp/gitError.log 2>&1
- globalError=$?
- if [[ $globalError -ne 0 ]];then
- gitErrorMenu
- fi
- fi
- else
- echo -e "$OK
|