Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 23/04/2013, à 02:59

fnux

[Résolu] Comment modifier un fichier en bash par un script ".sh"?

A nouveau bonjour tout le monde.

Je suis devant un nouveau problème que j'essaye de résoudre avec bash par un script ".sh".

Malheureusement, après avoir googeler tout le week-end sur ce sujet, je n'ai pas réussit à trouver la solution.

Voici donc le problème que je pose, ne sachant même pas si c'est possible en bash :

J'aimerai par exemple modifier le fichier /etc/sudoers

Avec Lucid (ce n'est qu'un exemple) ce fichier est comme ça :

# /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the man page for details on how to write a sudoers file.
#

Defaults	 env_reset
Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root	ALL=(ALL) ALL

# Allow members of group sudo to execute any command after they have
# provided their password
# (Note that later entries override this, so you might need to move
# it further down)
%sudo ALL=(ALL) ALL
#
#includedir /etc/sudoers.d

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

J'aimerai :

a) mettre un "#" devant la ligne Defaults     env_reset

b) ajouter en dessous de la ligne #Defaults   env_reset la ligne Defaults    env_keep="CLASSPATH"

c) ajouter ":/usr/local/go/bin" à la fin de la ligne Defaults    secure_path= MAIS avant le dernier signe double quote

d) enfin ajouter à la fin de ce fichier la ligne %sudo ALL=(ALL:ALL) NOPASSWD:ALL

Après modifications, le résultat devrait alors être comme ci-dessous.

# /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the man page for details on how to write a sudoers file.
#

#Defaults	  env_reset
Defaults    env_keep="CLASSPATH"
Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games:/usr/local/go/bin"

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root	ALL=(ALL) ALL

# Allow members of group sudo to execute any command after they have
# provided their password
# (Note that later entries override this, so you might need to move
# it further down)
%sudo ALL=(ALL) ALL
#
#includedir /etc/sudoers.d

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
%sudo ALL=(ALL) NOPASSWD:ALL

Est-ce possible en bash ?

Faire un petit programme en C serait une solution, mais j'aimerai le faire en bash si cela est réalisable.

Merci d'avance à tous les spécialistes de ce langage pour me donner la solution qui me permettrait alors de pouvoir modifier n'importe quel fichier texte.

Fnux.

Dernière modification par fnux (Le 06/05/2013, à 01:40)


N'engage pas un débat lors d'un dîner car celui qui n'a pas faim aura le dernier mot. - R. Whately
FWPBLA - The Froggies West Palm Beach Linux Association.

Hors ligne

#2 Le 23/04/2013, à 04:54

Yannou90

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Bonjour

fnux a écrit :

Faire un petit programme en C serait une solution, mais j'aimerai le faire en bash si cela est réalisable
.

Je presume que la programmation ne te fais pas peur , je te renvoi vers sed alors :
http://sed.sourceforge.net
http://sed.sourceforge.net/sed1line.txt

Hors ligne

#3 Le 23/04/2013, à 06:28

nesthib

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Tu as de multiples façons de faire, quelques exemples avec sed

fnux a écrit :

a) mettre un "#" devant la ligne Defaults     env_reset

sed '/^Defaults[[:blank:]]*env_reset/s/^/#/' /etc/sudoers
fnux a écrit :

b) ajouter en dessous de la ligne #Defaults   env_reset la ligne Defaults    env_keep="CLASSPATH"

sed '/^Defaults[[:blank:]]*env_reset/s/\(.*\)/#\1\nDefaults    env_keep="CLASSPATH"/' /etc/sudoers
fnux a écrit :

c) ajouter ":/usr/local/go/bin" à la fin de la ligne Defaults    secure_path= MAIS avant le dernier signe double quote

sed -n '/^Defaults[[:blank:]]*secure_path/s|\(.*\)"|\1:/usr/local/go/bin"|p' /etc/sudoers
fnux a écrit :

d) enfin ajouter à la fin de ce fichier la ligne %sudo ALL=(ALL:ALL) NOPASSWD:ALL

sed '$a%sudo ALL=(ALL:ALL) NOPASSWD:ALL' /etc/sudoers

NB. tu peux utiliser l'option « -i » de sed pour modifier un fichier en place, mais c'est une très mauvaise idée pour /etc/sudoers car si tu fais une erreur de syntaxe ton système sera inutilisable. L'idéal est de travailler sur une copie du fichier.


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#4 Le 23/04/2013, à 09:39

pingouinux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Bonjour,
Voici un script qui modifie le fichier sudoers (il ressemble évidemment beaucoup à la proposition de nesthib) :

$ cat modif_sudoers.sh
#!/bin/bash

old="$1"
new="$2"

cp "$old" "$new"
# a) et b)
sed -i 's/^\(Defaults\s*env_reset\)$/# \1\nDefaults    env_keep="CLASSPATH"/' "$new"
# c)
sed -i '/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#' "$new"
# d)
echo "%sudo ALL=(ALL:ALL) NOPASSWD:ALL" >>"$new"

Mode d'emploi :

sudo ./modif_sudoers.sh /etc/sudoers /etc/sudoers.new

Attention : Ta demande en d) ne correspond pas à l'exemple que tu donnes ensuite

Hors ligne

#5 Le 23/04/2013, à 10:02

Bousky

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Une manière de modifier sudoers en vérifiant la syntaxe :

./modif_sudoers.sh /etc/sudoers /etc/sudoers.tmp
if visudo -csf /etc/sudoers.tmp ; then
        mv -f /etc/sudoers.tmp /etc/sudoers
fi

Mais pour les tests, mieux vaut faire ça sur un fichier à part…

Dernière modification par Bousky (Le 23/04/2013, à 10:02)


Linux qui plante complètement ? Plus rien ne répond ? On peut toujours le redémarrer proprement :
Alt + SysRq + REISUB (Retourne En Islande Sur Un Bateau !)

Hors ligne

#6 Le 24/04/2013, à 03:19

fnux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Merci à vous trois de toutes vos contributions très utiles.

Décidément, la syntaxe de sed est encore bien plus compliquée que celle de sh ou de bash. wink

@pingouinux :

Après avoir pris la précaution de copier /etc/sudoers dans Temp-system-files/sudoers.new, ta commande :

sed -i 's/^\(Defaults\s*env_reset\)$/# \1\nDefaults env_keep="CLASSPATH"/' Temp-system-files/sudoers.new

fonctionne parfaitement.

Mais sous lucide, j'aimerai aussi pouvoir ajouter juste après la ligne Defaults env_keep="CLASSPATH" la ligne suivante :

Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin"

Sous lucide, j'ai donc essayé de faire comme ça :

#!/bin/sh
#
# Modify a copy of the system file /etc/sudoers
#
# get the Ubuntu distribution name (e.g. precise)
DISTRO=$(lsb_release -sc)
# get the distribution type (e.g. 64)
FLAVOR=$(getconf LONG_BIT)
# create a temporay folder
mkdir Temp-system-files-$FLAVOR
# create a copy of the original /etc/sudoers file into Temp-system-files-$FLAVOR with the extension ".new"
cp /etc/sudoers.original Temp-system-files-$FLAVOR/sudoers.new
# always disable the line Defaults env_reset, 
# and add env_keep=CLASSPATH" accordingly to $DISTRO
# and add or modify Defaults secure_path accordingly to $DISTRO
case $DISTRO in
    'lucid')
        #sed -i 's/^\(Defaults\s*env_reset\)$/# \1\nDefaults env_keep="CLASSPATH"/' Temp-system-files-$FLAVOR/sudoers.new;;
        sed -i 's/^\(Defaults\s*env_reset\)$/# \1\nDefaults env_keep="CLASSPATH" \1\nDefaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin"/' Temp-system-files-$FLAVOR/sudoers.new;;
    'precise')
        sed -i 's/^\(Defaults\s*env_reset\)$/# \1/' Temp-system-files-$FLAVOR/sudoers.new;;
esac
# add the relevant %sudo ligne accordingly to $DISTRO
case $DISTRO in
    'lucid')
        sed -i '$a%sudo ALL=(ALL) NOPASSWD:ALL' Temp-system-files-$FLAVOR/sudoers.new;;
    'precise')
        sed -i '$a%sudo ALL=(ALL:ALL) NOPASSWD:ALL' Temp-system-files-$FLAVOR/sudoers.new;;
esac

Mais "ça coince" avec l'erreur :

sed: -e expression #1, char 93: unknow option to `s'

et le caractère 93 est le signe souligné "_" de secure_path.

J'ai aussi essayé de mettre un \ devant le _ mais ça ne marche pas non plus. hmm

Je n'ai donc réussi qu'en changeant le délimiteur / par | et là, ça marche ! big_smile

Donc ça donne ça :

#!/bin/sh
#
# get the Ubuntu distribution name (e.g. precise)
DISTRO=$(lsb_release -sc)
# get the distribution type (e.g. 64)
FLAVOR=$(getconf LONG_BIT)
# create a temporay folder
mkdir Temp-system-files-$FLAVOR
# create a copy of the original files into Temp-system-files$FLAVOR
cp /etc/sudoers.original Temp-system-files-$FLAVOR/sudoers.new
# disable the line Defaults env_reset, and add env_keep=CLASSPATH" and add or modify Defaults secure_path accordingly to $DISTRO
case $DISTRO in
    'lucid')
        sed -i 's|^\(Defaults\s*env_reset\)$|# \1\nDefaults  env_keep="CLASSPATH" \1\nDefaults  secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin"|' Temp-system-files-$FLAVOR/sudoers.new;;
    'precise')
        sed -i 's/^\(Defaults\s*env_reset\)$/# \1/' Temp-system-files-$FLAVOR/sudoers.new;;
# It's above that I would like to add: sed -i '/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#'
esac
# add the relevant %sudo ligne accordingly to $DISTRO
case $DISTRO in
    'lucid')
        sed -i '$a%sudo ALL=(ALL) NOPASSWD:ALL' Temp-system-files-$FLAVOR/sudoers.new;;
    'precise')
        sed -i '$a%sudo ALL=(ALL:ALL) NOPASSWD:ALL' Temp-system-files-$FLAVOR/sudoers.new;;
esac

Mais avec precise, j'aimerai aussi pouvoir enchainer :

sed -i 's/^\(Defaults\s*env_reset\)$/# \1/' 
et 
sed -i '/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#'

mais je ne vois pas trop comment faire. à part peut-être comme ça : roll

sed -i 's/^\(Defaults\s*env_reset\)$/# \1/' Temp-system-files-$FLAVOR/sudoers.new && sed -i '/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#' Temp-system-files-$FLAVOR/sudoers.new

Merci d'avance car c'est vraiment compliqué quand on débute avec ce type de language. hmm

Et il faut vraiment que je comprenne comment sed fonctionne car j'ai d'autres fichiers à modifier pour terminer mon petit installateur.

Dernière modification par fnux (Le 24/04/2013, à 04:04)


N'engage pas un débat lors d'un dîner car celui qui n'a pas faim aura le dernier mot. - R. Whately
FWPBLA - The Froggies West Palm Beach Linux Association.

Hors ligne

#7 Le 24/04/2013, à 03:54

nesthib

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

En fait ton 93e caractère n'est pas le « _ » mais le « u » de « /usr ». Tu ne peux pas à la fois utiliser le caractère « / » comme séparateur pour sed (s/…/…/) et comme séparateur de chemin sans échappement. La solution la plus simple est de changer de séparateur pour sed (ex. s|…|…|)

sed -i 's|^\(Defaults\s*env_reset\)$|# \1\nDefaults env_keep="CLASSPATH" \1\nDefaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin"|' Temp-system-files-$FLAVOR/sudoers.new

Attention, je n'ai pas corrigé mais tu as un « \1 » en trop à mon avis (le second).

Une remarque, pense que sur tous les systèmes la ligne « Defaults    env_reset » peut éventuellement contenir d'autres options, il serait plus sage de prendre en compte la ligne entière (« ^\(Defaults\s*env_reset.*\) »)

Tu peux enchaîner plusieurs commandes avec l'option « -e ».


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#8 Le 24/04/2013, à 06:50

pingouinux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

fnux   #6 a écrit :

Mais avec precise, j'aimerai aussi pouvoir enchainer :

sed -i 's/^\(Defaults\s*env_reset\)$/# \1/' 
et 
sed -i '/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#'

Tu peux faire comme ceci (un seul sed, les deux expressions séparées par ;) :

sed -i 's/^\(Defaults\s*env_reset\)$/# \1/;/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#' Temp-system-files-$FLAVOR/sudoers.new

Explication sur l'utilisation de && entre les deux commandes :

# commande2 est exécutée systématiquement après commande1
commande1
commande2
# commande2 n'est exécutée que si commande1 s'est terminée normalement
commande1 && commande2

Hors ligne

#9 Le 24/04/2013, à 15:04

fnux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Salut pingouinux.

nesthib a écrit :

En fait ton 93e caractère n'est pas le « _ » mais le « u » de « /usr ». Tu ne peux pas à la fois utiliser le caractère « / » comme séparateur pour sed (s/…/…/) et comme séparateur de chemin sans échappement. La solution la plus simple est de changer de séparateur pour sed (ex. s|…|…|)

sed -i 's|^\(Defaults\s*env_reset\)$|# \1\nDefaults env_keep="CLASSPATH" \1\nDefaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin"|' Temp-system-files-$FLAVOR/sudoers.new

C'est bien ce que j'avais réussi à découvrir.

Mais ce qui me laisse maintenant très perplexe est que ta commande :

 sed -i 's/^\(Defaults\s*env_reset\)$/# \1/;/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#' Temp-system-files-$FLAVOR/sudoers.new

fonctionne très bien, alors qu'il y a aussi un \ comme séparateur et un _ dans secure_path. hmm

J'ai essayé (pour voir) de remplacer le / par | mais bien entendu (tu vas rigoler) ça ne fonctionne pas (du moins comme je l'espérais)! roll

sed -i 's|^\(Defaults\s*env_reset*\)$|# \1;/^Defaults\s*secure_path="s#"\s*$#:/usr/local/go/bin"#|' Temp-system-files-$FLAVOR/sudoers.new

Mon mauvais exemple ci-dessus ajoute alors la chaine ;/^Defaultss*secure_path="s#"s*$#:/usr/local/go/bin"# à la ligne #Defaults env-reset (ce qui ne veut évidemment strictement rien dire ):

Voici le résultat de mon incompétence : mad

# Defaults	env_reset;/^Defaultss*secure_path="s#"s*$#:/usr/local/go/bin"#
Defaults	secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

Décidément, sed est vraiment très complexe. hmm

Question complémentaire : dans un case, est-il possible de faire un case multiple ?

Je m'explique :

case $DISTRO in
    'lucid', 'maverick', 'natty')
        bla bla bla;;
    'oneiric')
        autre bla bla bla;;
    'precise', 'quantal', 'raring')
        encore autre bla bla bla;;
    *)
        rien
esac

Dernière modification par fnux (Le 24/04/2013, à 15:14)


N'engage pas un débat lors d'un dîner car celui qui n'a pas faim aura le dernier mot. - R. Whately
FWPBLA - The Froggies West Palm Beach Linux Association.

Hors ligne

#10 Le 24/04/2013, à 15:28

nesthib

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Le « _ » ne pose absolument aucun problème, quand tu as compté tes 93 caractères, il ne fallait pas prendre en compte les caractères d'échappement « \ ». Oublie donc le « _ », il ne joue aucun rôle.

La commande :

sed -i 's/^\(Defaults\s*env_reset\)$/# \1/;/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#' Temp-system-files-$FLAVOR/sudoers.new

est composée des parties suivantes :
substitution 1

s/^\(Defaults\s*env_reset\)$/# \1/

Reconnaissance d'un motif

/^Defaults\s*secure_path="/

Et substitution 2 sur les lignes contenant ce motif

s#"\s*$#:/usr/local/go/bin"#

Quand tu essaie de changer ton séparateur, tu peux le faire pour chacune des substitutions, uniquement. Si tu regardes bien ta proposition ça n'est pas ce que tu as fait. Tu as remplacé les 2 premiers séparateurs de la substitution 1, supprimé le troisième et ajouté un séparateur après le troisième séparateur de la seconde substitution (tu suis ? tongue)

En couleur, Il fallait faire :
s||| ; // s###
et tu as fait :
s||… ; // s#…s##|

ce que sed ne comprend pas (à juste titre)

sed est très puissant mais la syntaxe doit être respectée (comme pour tout langage de programmation).

edit.
Pour le case tu peux faire :

case $DISTRO in
  lucid|maverick|natty) … ;;
  oneiric) … ;;
  precise) … ;;
esac

Dernière modification par nesthib (Le 24/04/2013, à 15:34)


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#11 Le 24/04/2013, à 16:50

fnux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Re salut nesthib,

nesthib a écrit :

Quand tu essaie de changer ton séparateur, tu peux le faire pour chacune des substitutions, uniquement. Si tu regardes bien ta proposition ça n'est pas ce que tu as fait. Tu as remplacé les 2 premiers séparateurs de la substitution 1, supprimé le troisième et ajouté un séparateur après le troisième séparateur de la seconde substitution (tu suis ? tongue)

En couleur, Il fallait faire :
s||| ; // s###
et tu as fait :
s||… ; // s#…s##|

ce que sed ne comprend pas (à juste titre)

sed est très puissant mais la syntaxe doit être respectée (comme pour tout langage de programmation).

Donc si j'ai bien tout compris (ce dont je doute un peu... beaucoup... passionnément quand même) wink

les séparateurs / de la commande suivante sont en rouge souligné:
sed -i 's/^\(Defaults\s*env_reset\)$/# \1/;/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#' sudoers.new;;
            ^                                        ^      ^

Je devrai donc pouvoir les remplacer par |

sed -i 's|^\(Defaults\s*env_reset\)$|# \1|;/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#' sudoers.new;;
            ^                                        ^     ^

Et ça marche !

Mais d'après ce que j'ai cru comprendre, je devrais aussi remplacer les séparateurs de la seconde partie de cette commande (ici en vert).

sed -i 's|^\(Defaults\s*env_reset\)$|# \1|;/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#' sudoers.new;;
                                                              ^                                         ^     et je ne trouve pas le 3ème / de fin !

et là :

sed -i 's|^\(Defaults\s*env_reset\)$|# \1|;|^Defaults\s*secure_path="|s#"\s*$#:/usr/local/go/bin"#' sudoers.new;;
                                                              ^                                         ^     car je ne trouve pas le 3ème / de fin (ou je n'ai rien compris)!

Donc, ça ne marche plus ! hmm

Bref, j'en perds mon latin... pardon je voulais dire mon sed ! roll

Dernière modification par fnux (Le 24/04/2013, à 17:02)


N'engage pas un débat lors d'un dîner car celui qui n'a pas faim aura le dernier mot. - R. Whately
FWPBLA - The Froggies West Palm Beach Linux Association.

Hors ligne

#12 Le 24/04/2013, à 17:07

pingouinux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#
Le séparateur est ici #. Les / délimitent l'expression régulière qui caractérise la ligne que l'on veut traiter.

Hors ligne

#13 Le 24/04/2013, à 17:42

fnux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Re re salut pingouinux.

pingouinux a écrit :

/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#
Le séparateur est ici #. Les / délimitent l'expression régulière qui caractérise la ligne que l'on veut traiter.

Ce qui veut dire que chaque commande de la ligne sed peut avoir un séparateur différent ?

Dans ce cas précis, la ligne complète :

sed -i 's|^\(Defaults\s*env_reset*\)$|# \1|;/^Defaults\s*secure_path="/s|"\s*$|:/usr/local/go/bin"|' sudoers.new;;

fonctionne exactement de la même façon que :

sed -i 's|^\(Defaults\s*env_reset*\)$|# \1|;/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#' sudoers.new;;

Alors, quel est l'intérêt (ou l'avantage) d'utiliser deux séparateurs différents ?

Dernière modification par fnux (Le 24/04/2013, à 17:47)


N'engage pas un débat lors d'un dîner car celui qui n'a pas faim aura le dernier mot. - R. Whately
FWPBLA - The Froggies West Palm Beach Linux Association.

Hors ligne

#14 Le 24/04/2013, à 17:51

pingouinux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Alors, quel est l'intérêt (ou l'avantage) d'utiliser deux séparateurs différents ?

C'est à cause des / dans la chaîne de remplacement. On a le choix entre

/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#

et

/^Defaults\s*secure_path="/s/"\s*$/:\/usr\/local\/go\/bin"/

Hors ligne

#15 Le 24/04/2013, à 18:28

fnux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

pingouinux a écrit :

Alors, quel est l'intérêt (ou l'avantage) d'utiliser deux séparateurs différents ?

C'est à cause des / dans la chaîne de remplacement. On a le choix entre

/^Defaults\s*secure_path="/s#"\s*$#:/usr/local/go/bin"#

et

/^Defaults\s*secure_path="/s/"\s*$/:\/usr\/local\/go\/bin"/

OK et surtout merci pour l'explication sur les séparateurs.

Bon, maintenant j'essaye de décortiquer la commande suivante qui fonctionne très bien :

sed -i '/^Defaults\s*secure_path="/s|"\s*$|:/usr/local/go/bin"|' sudoers.new

pour l'adapter à /etc/environment qui ne contient que la ligne :

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"

et à la quelle je voudrais bien ajouter :/usr/local/go/bin avant le dernier double quote.

donc j'essaye :

sed -i '/^PATH\s*PATH="/s|"\s*$|:/usr/local/go/bin"|' environment.new

et bien entendu ça ne marche pas (il n'y a pas de message d'erreur de sed mais la ligne n'est pas modifiée)! (trop naze le Fnux). tongue

Où est-ce que j'ai encore faux ?

Dernière modification par fnux (Le 24/04/2013, à 18:36)


N'engage pas un débat lors d'un dîner car celui qui n'a pas faim aura le dernier mot. - R. Whately
FWPBLA - The Froggies West Palm Beach Linux Association.

Hors ligne

#16 Le 24/04/2013, à 18:48

pingouinux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

C'est

sed -i '/^PATH="/s|"\s*$|:/usr/local/go/bin"|' environment.new

mais il ne faut pas qu'il y ait d'autres lignes commençant par PATH=, car elles seront modifiées aussi.

Dernière modification par pingouinux (Le 24/04/2013, à 18:53)

Hors ligne

#17 Le 24/04/2013, à 20:24

fnux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Re re re...

pingouinux a écrit :

C'est

sed -i '/^PATH="/s|"\s*$|:/usr/local/go/bin"|' environment.new

mais il ne faut pas qu'il y ait d'autres lignes commençant par PATH=, car elles seront modifiées aussi.

Donc, dans le cas du fichier /etc/login.defs, ce fichier ne contient que 2 lignes commençant par ENV_SUPATH et ENV_PATH qui sont :

ENV_SUPATH    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
et
ENV_PATH    PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

(mais qui peuvent avoir été modifiées).

Donc les commandes suivantes devraient aussi fonctionner ?

sed -i '/^ENV_SUPATH=/s|"\s*$|:/usr/local/go/bin"|' login.defs.new
sed -i '/^ENV_PATH=/s|"\s*$|:/usr/local/go/bin"|' login.defs.new

Et là non plus ça ne fonctionne pas (pas de message d'erreur de sed, mais pas de modification des lignes non plus).

Il est vrai que ces 2 lignes ne se terminent pas par une double quote et ça doit surement être une partie ma bètise.

Mais je ne sais pas comment corriger car si ces lignes ont été modifiées, je dois juste ajouter :/usr/local/go/bin à la fin sans modifer autre chose.

Décidément, je suis un peu long à la détente big_smile

J'ai trouvé : c'était ma première condition qui était fausse :je dois mettre ENV_SUPATH et non ENV_SUPATH= ! Fnux le bourrin ! lol

Mais j'ai quand même une autre question :

Comment ajouter 2 lignes à la suite en une seule commande ?

Exemple dans le fichier limits.conf, j'aimerai ajouter :

* soft nofile 200000
* hard nofile 200000

et si possible juste avant la dernière ligne qui est : # end of file (juste pour faire plus propre que de les ajouter derrière).

sed -i '$a* soft nofile 200000' limits.conf.new
sed -i '$a* hard nofile 200000' limits.conf.new

Dernière modification par fnux (Le 24/04/2013, à 20:42)


N'engage pas un débat lors d'un dîner car celui qui n'a pas faim aura le dernier mot. - R. Whately
FWPBLA - The Froggies West Palm Beach Linux Association.

Hors ligne

#18 Le 24/04/2013, à 20:39

pingouinux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Pour modifier la ligne, que " soit présent ou non :

sed -i -r '/^ENV_SUPATH=/s|("?)\s*$|:/usr/local/go/bin\1|' login.defs.new

Hors ligne

#19 Le 24/04/2013, à 20:49

fnux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

pingouinux a écrit :

Pour modifier la ligne, que " soit présent ou non :

sed -i -r '/^ENV_SUPATH=/s|("?)\s*$|:/usr/local/go/bin\1|' login.defs.new

Désolé, j'étais en train de corriger le message précédent pendant que tu m'as répondu.

Bon, au fait à quoi sert le \1 avant le dernier séparateur | (car ça marche aussi sans) ?

Avec ma dernière question sur l'ajout de 2 lignes en une seule commande dans limits.conf et si possible avant la dernière ligne du fichier qui se termine par # end of file (pour faire plus propre), je devrais être capable de terminer mon installateur, et même en couleur.

Je bosse dessus et je reviens dès que ça marche.

Merci encore de toutes tes super explications ainsi que les contributions de.nesthib et Bousky.

A très vite.

Dernière modification par fnux (Le 24/04/2013, à 20:57)


N'engage pas un débat lors d'un dîner car celui qui n'a pas faim aura le dernier mot. - R. Whately
FWPBLA - The Froggies West Palm Beach Linux Association.

Hors ligne

#20 Le 24/04/2013, à 21:04

nesthib

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Le problème avec sed c'est que souvent le gens limitent son utilisation à la commande de substitution « s/…/…/ ». En réalité sed sait faire beaucoup plus de choses (c'est un langage Turing-complet). Pour résumer (car tu trouveras de multiples sites détaillant le fonctionnement de sed), sed lit un fichier ligne à ligne et exécute pour chacune les commandes en argument (sed = stream editor).

Par exemple :
Trouver les lignes correspondant à un motif (= grep) :

sed -n '/motif/p' fichier

Si on rencontre le /motif/, on affiche la ligne (« p »).
(l'option « -n » permet de ne pas afficher explicitement les lignes, ce que sed fait par défaut)

Commenter les lignes qui comportent le motif « ABC » :

sed '/ABC/s/^/#/' fichier

Pour chaque ligne, si la ligne comporte « ABC », on substitue le début (ici, on ne fait donc qu'ajouter) par « # ».

En espérant que tu comprennes mieux le principe de sed. Si tu veux aller plus loin il est possible de faire des boucles, des conditions, d'enregistrer des information dans des tampons…


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#21 Le 24/04/2013, à 21:37

pingouinux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

fnux a écrit :

j'aimerai ajouter :

* soft nofile 200000
* hard nofile 200000

et si possible juste avant la dernière ligne qui est : # end of file (juste pour faire plus propre que de les ajouter derrière).

sed -i '$i* soft nofile 200000\n* hard nofile 200000' limits.conf.new

Bon, au fait à quoi sert le \1 avant le dernier séparateur | (car ça marche aussi sans) ?

\1 est replacé par le contenu du premier groupe de parenthèses dans la chaîne de recherche ("?), qui signifie 0 ou 1 caractère ".
Ça marche dans ton exemple parce qu'il n'y avait pas de " à la fin de la ligne.

Dernière modification par pingouinux (Le 16/05/2013, à 06:41)

Hors ligne

#22 Le 30/04/2013, à 05:15

fnux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Re coucou pingouinux, nesthib, Bousky et tous les autres aussi.

Bon, depuis notre dernier échange du 24 avril, je me suis attelé à mon script (qui fait quand même 1027 lignes (commentaires et mise en couleur inclus).

Je reste cependant sur deux "obstacles" pour le terminer. hmm

Le premier cas est la modification du fichier /etc/sudoers (en passant bien sur par un fichier intermédiaire).

En effet, si ce fichier n'a pas été modifié, il contient la ligne suivante:

Defaults    env_reset

Comme j'ai besoin de désactiver cette ligne et d'ajouter une ligne à la ligne suivante, la commande suivante marche très bien :

sed -i 's|^\(Defaults\s*env_reset*\)$|# \1|;/^Defaults\s*secure_path="/s|"\s*$|:/usr/local/go/bin"|' sudoers.modified

Par contre, si cette ligne a été modifiée, (par exemple pour y ajouter : ",pwfeedback  " qui affichera des étoiles lors de la saisie des mots de passe), on aura alors une ligne du type :

Defaults    env-reset,pwfeedback

Et bien sur, dans ce cas là, la commande ci dessus ne fonctionne plus ! mad

J'ai cherché tout ce week-end comment faire pour désactiver cette ligne et ne recopier en dessous que juste ce qui suit env_reset, (soit seulement "Defaults    pwfeedback") mais bien entendu je n'y suis pas arrivé !

Please... Help!

Mon second problème qui est moins important concerne le fichier /etc/environment (ou d'ailleurs n'importe quel autre fichier).

Dans certains cas (sous Debian squeeze entre autre), par défaut ce fichier est présent mais il est vide.

La commande :

ls -l /etc/environment 

indique d'ailleurs alors :

-rw-r--r-- 1 root root 0 Mar  3 13:10 /etc/environment

Or, si je veux ajouter deux lignes à ce fichier comme par exemple :

sed -i '$a'PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin"' >> environment.modified;$aCLASSPATH=$CLASSPATH:/usr/share/java/scala-library.jar' environment.modified

ça ne marche pas non plus ! hmm

J'en perds mon latin (pardon mon bash). lol

J'ai résolu ce problème par :

sudo echo 'PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin"' >> environment.modified && sudo echo 'CLASSPATH=$CLASSPATH:/usr/share/java/scala-library.jar' >> environment.modified

mais je n'ai pas réussi à le faire avec sed ! hmm

Je dois vraiment être trop naze ! roll

Dernier point (de détail) :

J'ai noté que dans certains cas, des scripts ".sh" pouvaient s'exécuter en faisant un double click sur leur icône ou en tapant simplement ./ suivit du nom du script.

Que faut-il faire pour que le script que j'essaye de mettre au point se comporte aussi de cette manière. hmm

Merci d'avance encore une fois de votre aide (car je suis presque au bout de mon effort). big_smile


N'engage pas un débat lors d'un dîner car celui qui n'a pas faim aura le dernier mot. - R. Whately
FWPBLA - The Froggies West Palm Beach Linux Association.

Hors ligne

#23 Le 30/04/2013, à 06:47

pingouinux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Bonjour fnux,

1ère question :

sed -i 's|^\(Defaults\s*env_reset.*\)$|# \1|;/^Defaults\s*secure_path="/s|"\s*$|:/usr/local/go/bin"|' sudoers.modified

Attention : env-reset est différent de env_reset

2ème question :

echo -e 'PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin"\nCLASSPATH=$CLASSPATH:/usr/share/java/scala-library.jar'  >>environment.modified

Dernière modification par pingouinux (Le 30/04/2013, à 07:40)

Hors ligne

#24 Le 30/04/2013, à 11:51

Josepe36

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Bonjour
je me permet de m'incruster, trés intéressant sed, mais sincérement est ce vraiment utile dans ce cas ?
En se référant sur le tout premier post :

#!/bin/bash

SUDOERS_TMP=sudoers2

    LOOP(){
        # READ AND MODIFY SUDOERS IN OUTPUT FILE
        cat /etc/sudoers |
        while read line
        do
            if echo $line | grep "Defaults"| grep "env_reset" 1>/dev/null
                then
                    echo "#"$line >> $SUDOERS_TMP
                    echo 'Defaults    env_keep="CLASSPATH"' >> $SUDOERS_TMP
                else
                    if echo $line | grep "Defaults"| grep "secure_path=" 1>/dev/null
                        then
                            path=$(echo $line | cut -d "=" -f2 | cut -d '"' -f2)
                            echo "Defaults    secure_path="'"'$path":/usr/local/go/bin"'"' >> $SUDOERS_TMP
                        else
                            echo $line  >> $SUDOERS_TMP   
                    fi
            fi
        done
        # CONCLUDE THE FILE WITH THE LAST LINE
        echo "%sudo ALL=(ALL) NOPASSWD:ALL" >> $SUDOERS_TMP 
    }

LOOP 

Développeur distribution Hybryde
www.hybryde.org

Hors ligne

#25 Le 30/04/2013, à 19:17

fnux

Re : [Résolu] Comment modifier un fichier en bash par un script ".sh"?

Bonjour Josepe36,

Josepe36 a écrit :

Bonjour
je me permet de m'incruster, trés intéressant sed, mais sincérement est ce vraiment utile dans ce cas ?

Il y a surement d'autres solutions que l'utilisation de sed pour répondre à mon besoin, mais comme je débute avec Linux et que les solutions qui m'ont été enseignées par pingouinux, nesthib et Bousky fonctionnent et qu'en plus je ne connais pas encore vraiment le fonctionnement de grep, je m'en tiens pour l'instant à ce que j'ai appris ici.

Merci quand même car ton intrusion est parfaitement valide et me donne d'autres idées. wink

Il me reste quand même un soucis à régler :

Le script que j'ai presque terminé à pour but d'installer plusieurs packages depuis leurs sources respectives, dont en particulier Go, Mono et Node.

Or le temps d'installation de Mono et de Node demande en général environ 45 minutes (sur mon PC qui est assez musclé) et dépasse donc largement le temps de grâce pour demander le mot de passe utilisateur suite à l'utilisation de sudo (15 minutes par défaut).

J'ai bien trouvé une commande à insérer dans le fichier /etc/sudoers pour modifier ce délai de grâce :

timestamp_timeout=60     pour passer ce délai à 60 minutes

mais il faut alors rebooter pour que le nouveau délai de grâce devienne actif.

J'ai bien essayé de passer cette commande dans une session terminal, mais le délai de grâce ne change pas. hmm

Ma question est donc : y a-t-il une commande équivalente à entrer dans une session terminal pour que ce délai de grâce soit modifié, au moins pour la session en cours ?

Merci d'avance de toute suggestion à ce propos.

PS: j'utilise "sudo" à plusieurs endroits de mon script, mais je ne veux pas lancer mon script avec les privilèges de root car cela me pose un sérieux problème sous Debian par rapport à Ubuntu et que je tiens à ce que ce script soit le même pour ces deux OS (quitte à faire des tests de l'OS et même de sa version dans le script).

Dernière modification par fnux (Le 30/04/2013, à 19:17)


N'engage pas un débat lors d'un dîner car celui qui n'a pas faim aura le dernier mot. - R. Whately
FWPBLA - The Froggies West Palm Beach Linux Association.

Hors ligne