Script zu bearbeiten einer conf Datei

satriani

satriani

SysLion
Script zum bearbeiten einer conf Datei

Hallo liebe Leute,

ich baue mir ein Script, der über eine Funktion verfügt zum verwalten einer Konfigurationsdatei. Hier der Code:
Code:
#!/bin/sh

jail_path=/srv/mysql
jail_ip=127.10.10.1
jail_name=mysql

host_jail_conf="${jail_name} {
path = ${jail_path};
mount.devfs;
allow.mount;
mount;
host.hostname = ${jail_name};
ip4.addr = ${jail_ip};
interface = lo1;
exec.start = \"/bin/sh /etc/rc\";
exec.stop = \"/bin/sh /etc/rc.shutdown\";
}
"
        if [ -z "$(grep -ir '${host_jail_conf}' /etc/jail.conf)" ]; then
          echo "$host_jail_conf" >> /etc/jail.conf
        else
          read -r -p "Settings allredy exist. Do you want to remove this settings for $jail_name? [Y/N] " response
          case $response in
[yY][eE][sS][jJ]|[yY])
sed -i "" "s/$host_jail_conf//g" /etc/jail.conf
exit
;;
[nN]|[nN])
echo "Good bye!"
exit
;;
  esac
        fi
Leider tut es nicht was es soll. Nämlich, wie man aus dem Code entnehmen kann, wenn $host_jail_conf in der /etc/jail.conf bereits vorhanden ist, dann Vorschlagen ob der komplette Abschnitt $host_jail_conf aus der /etc/jail.conf entfent werden soll. Leider wir es nicht gefragt nach der Ausführung, sondern jedes mal mit weiterem $host_jail_conf ergänzt. Was ist falsch an dem Code?

Danke im Voraus.
Gruß.
 
Zuletzt bearbeitet:
Code:
...
        if [ -z "$(grep -ir [COLOR="#FF0000"]'${host_jail_conf}'[/COLOR] /etc/jail.conf)" ]; then
...
Die Vari wird wegen der einfachen Anführungszeichen nicht aufgelöst. Mit Doppelten sollte es gehen (falls grep die ganzen Sonderzeichen in dem mehrzeiligen Suchmuster nicht anders interpretiert, als vorgesehen).
 
Recht haste Spröde, danke dafür. :]
Nun will er nicht überschreiben bzw. entfernen, irgendwas ist faul am
Code:
sed -i "" "s/$host_jail_conf//g" /etc/jail.conf
unterminated substitute pattern
Ich mach mich auf die Suche :)
 
So gut kenne ich sed nicht, aber wuerde sed bei dieser Syntax nicht den leeren String als das Muster und den zweiten dann bereits als Dateinamen interpretieren? Ich wuerde es mit
Code:
sed -i  "s/$host_jail_conf//g" /etc/jail.conf
versuchen.
 
Danke tgruene,

doch leider kein Erfolg.
sed: 1: "/etc/jail.conf": invalid command code j
Im Netz kann ich dazu auch nichts finden, wie man mehrere Zeilen mit sed auf einmal ändern kann.
 
unterminated substitute pattern

Ich nehme an, dass in der Variable
Code:
$host_jail_conf
in
Code:
sed -i  "s/$host_jail_conf//g" /etc/jail.conf
ein oder mehrere Slashes ("/") vorkommen, welche du im sed-Statement ja als Separatoren definiert hast.
Da musst du wohl einen anderen Seperator wählen, oder die Slashes escapen.

MfG

Schard
 
PS:
Danke tgruene,

doch leider kein Erfolg.

Code:
sed: 1: "/etc/jail.conf": invalid command code j

Im Netz kann ich dazu auch nichts finden, wie man mehrere Zeilen mit sed auf einmal ändern kann.

Jetzt benutzt du wohl
Code:
 sed -j
statt, wie von tgruene vorgeschlagen
Code:
sed -i

Schard
 
Ich nehme an, dass in der Variable
Code:
$host_jail_conf
in
Code:
sed -i  "s/$host_jail_conf//g" /etc/jail.conf
ein oder mehrere Slashes ("/") vorkommen, welche du im sed-Statement ja als Separatoren definiert hast.
Da musst du wohl einen anderen Seperator wählen, oder die Slashes escapen.
Ja, du hast recht. Wie man aus dem Code im ersten post entnehmen kann ist die Variable:
Code:
host_jail_conf="${jail_name} {
path = ${jail_path};
mount.devfs;
allow.mount;
mount;
host.hostname = ${jail_name};
ip4.addr = ${jail_ip};
interface = lo1;
exec.start = \"/bin/sh /etc/rc\";
exec.stop = \"/bin/sh /etc/rc.shutdown\";
}
"
Die auch Slashes beinhaltet. Ich kann die Slashes nicht ohne weiteres escapen, mit einem anderen Separator zB.
Code:
sed -i "" "s@$host_jail_conf@@g" /etc/jail.conf
funktionierts auch nicht :(
unterminated substitute pattern
 
Hi,

statt mit sed auf den ganzen Eintrag für ein Jail loszugehen, könntest du auch einfach versuchen, den Absatz, der mit dem Jail-Namen beginnt bis zur nächsten Leerzeile löschen:
Code:
sed -i "/${jail_name} {/,/^$/d' /etc/jail.conf
Ich denke, 'sed' wird immer etwas unhandlich, wenn er Strings verarbeiten soll, die über mehrere Zeilen gehen ;)

Gruss, A.
 
Danke floyd62,
aber ich glaube da hat sich ein Fehler eingeschlichen
Code:
sed -i [COLOR="#FF0000"][B]"[/B][/COLOR]/${jail_name} {/,/^$/d[COLOR="#FF0000"][B]'[/B][/COLOR] /etc/jail.conf

so
Code:
sed -i '/'${jail_name}' {/,/^$/d' /etc/jail.conf
oder so
Code:
sed -i "/${jail_name} {/,/^$/d" /etc/jail.conf
ergibt das
sed: 1: "/etc/jail.conf": invalid command code j

Das muss nicht unbedingt sed sein, vielleicht hast du bessere Alternativen :)
 
Hi,

du hast natürlich recht - ich wollte double quotes ("..."), weil sonst die Shell ja die Variable nicht auswertet.

Die Meldung mit "invalid command code j" kann ich hier nicht nachvollziehen.

Ich habe hier noch ein bisschen gebastelt, und bei mir scheint das Folgende jetzt zu laufen:
Code:
#!/bin/sh

jail_path=/srv/mysql
jail_ip=127.10.10.1
jail_name=mysql

CONFIG=/var/tmp/jail.conf

host_jail_conf="${jail_name} {
path = ${jail_path};
mount.devfs;
allow.mount;
mount;
host.hostname = ${jail_name};
ip4.addr = ${jail_ip};
interface = lo1;
exec.start = \"/bin/sh /etc/rc\";
exec.stop = \"/bin/sh /etc/rc.shutdown\";
}
"

if grep -irq "^${host_jail_conf} " $CONFIG; then
        read -r -p "Settings already exist. Do you want to remove the settings for $jail_name? [Y/N] " response
        case $response in
        [Yyj])
                sed -i "/${jail_name}/,/^$/d" $CONFIG
                exit
                ;;
        [nN])
                echo "Good bye!"
                exit
                ;;
        esac
else
        echo "$host_jail_conf" >>$CONFIG
        echo "ADDED"
fi

Zur Erläuterung: in der "if grep ..." Abfrage interessiert mich überhaupt nicht, was grep findet, sondern nur ob überhaupt, d.h. der Exit-Status, daher verwende ich "-q". Und nach der Bestätigung lösche ich den Absatz für den Jail "${jail_name}" (d.h. alle solchen Absätze) mit dem sed-Befehl wie oben angedeutet.

Hoffe, das hilft dir weiter - Gruss, A.
 
sed: 1: "/var/tmp/jail.conf": undefined label 'mp/jail.conf'
Ich verstehe es nicht, liegt es vielleicht daran, dass wir verschiedene Systeme benutzen?
FreeBSD 9.1-RELEASE #0 r243825
 
Hi,

kann gut sein - habe hier auf Linux getestet; weiss nicht, ob der FreeBSD-sed die -i-Option genau so verarbeitet wie GNU-sed unter Linux; als Workaround könntest du die sed -Zeile auch einfach ersetzen mit etwas wie
Code:
sed  "/${jail_name}/,/^$/d" <$CONFIG >$CONFIG.$$
cmp -s $CONFIG $CONFIG.$$ && { echo $CONFIG unchanged; rm -f $CONFIG.$$; } || { mv $CONFIG $CONFIG.OLD; mv $CONFIG.$$ $CONFIG; }
Das Ganze jetzt natürlich ungetestet und rein theoretisch ...

Gruss, A.
 
ungetestet und rein theoretisch? :think:
Dafür erfüllt es seinen Zweck, also ich danke dir vielmals, darauf wäre ich nie gekommen :respekt:
 
Ich habe etwas aufgeräumt
Code:
#!/bin/sh

jail_path=/srv/mysql
jail_ip=127.10.10.1
jail_name=mysql

CONFIG=/etc/jail.conf

host_jail_conf="${jail_name} {
path = ${jail_path};
mount.devfs;
allow.mount;
mount;
host.hostname = ${jail_name};
ip4.addr = ${jail_ip};
interface = lo1;
exec.start = \"/bin/sh /etc/rc\";
exec.stop = \"/bin/sh /etc/rc.shutdown\";
}
"

if grep -irq "^${host_jail_conf} " $CONFIG; then
        read -r -p "Settings already exist. Do you want to remove the settings for $jail_name? [Y/N] " response
        case $response in
        [Yyj])
                sed -i "" "/${jail_name}/,/^$/d" $CONFIG
                exit
                ;;
        [nN])
                echo "Good bye!"
                exit
                ;;
        esac
else
        echo "$host_jail_conf" >>$CONFIG
        echo "ADDED"
fi
Funktioniert ganz gut, bis auf das grep Problem. Funktioniert leider nicht so wie es soll.
Ändern sich die Variablen jail_path, jail_ip und jail_name, so wird es nicht erkannt und schlägt vor die conf zu bereinigen. :think:
 
Hi,

das wird ja noch richtig interessant ;-)

Zunächst einmal hat sich bei mir im grep-Kommando ein Fehler eingeschlichen: da ich beim Experimentieren zunächst nach dem $jail_name gesucht hatte, habe ich da ein Leerzeichen nach der Variablen stehen lassen. Selbst wenn grep also funktionieren würde wie eigentlich erhofft, so würde bei der Suche wegen dieses in der jail.conf nicht vorhandenen Leerzeichens nie etwas gefunden.

Ein weiteres Problem scheint mir zu sein, dass grep den Search-String (evtl. weil mehrzeilig, möglicherweise auch wegen der enthaltenen {}-Klammern, die er als Wiederholungen innerhalb des Patterns interpretieren könnte) nicht so verarbeitet, wie wir das benötigen würden. Ein Versuch mit
Code:
FOUND=$(grep "${host_jail_conf}" $CONFIG 2>/dev/null); echo -e "FOUND:\n*\n$FOUND\n*\n"
ist da ganz aufschlussreich. Es wird wohl eine ganze Menge mehr gefunden, als gedacht - damit ist auch der Exit-Status nicht mehr brauchbar.

(NB: die-r Option für grep ist vermutlich überflüssig; ob -i nötig ist um z.B. unterschiedliche Schreibweise der Jail-Names abzufangen, kann ich nicht beurteilen.)

Ein alternativer Ansatz wäre jetzt z.B. mit sed die bestehenden Einträge für einen $jail_name aus der jail.conf auszulesen und die mit dem neu zu erstellenden Eintrag zu vergleichen, also
Code:
OLD=$(sed -ne "/${jail_name}\ /,/^$/p" $JAIL_CONF 2>/dev/null)
NEW=$(echo "${host_jail_conf}")
if [ "$OLD" = "$NEW" ]; then
anstelle der 'grep'-Abfrage. Damit sollten neue Jails auch als neu erkannt werden ($OLD müsste leer sein), und sollte ein Eintrag für $jail_name bereits existieren, kannst den nach Bestätigung löschen und ggf. durch den neuen ersetzen lassen. Das könnte dann für den Anfang etwa so aussehen:
Code:
#!/bin/sh


# JAIL_CONF=`pwd`/jail.conf
JAIL_CONF=/etc/jail.conf


ASK() {
        read -p "$1${2:+ [default: $2]}: " RESPONSE
        [ "$RESPONSE" ] || RESPONSE="$2"
        echo "$RESPONSE"
}


jail_name=$(ASK "Jail Name" "mysql")
jail_path=$(ASK "Jail Path" /srv/$jail_name)
jail_ip=$(ASK "Jail IP" 127.10.10.1)


host_jail_conf="${jail_name} {
        path = ${jail_path};
        mount.devfs;
        allow.mount;
        mount;
        host.hostname = ${jail_name};
        ip4.addr = ${jail_ip};
        interface = lo1;
        exec.start = \"/bin/sh /etc/rc\";
        exec.stop = \"/bin/sh /etc/rc.shutdown\";
}
"


echo -e "NEW HOST_JAIL_CONF:\n*\n$host_jail_conf\n*\n"

# FOUND=$(grep "${host_jail_conf}" $JAIL_CONF 2>/dev/null); echo -e "FOUND:\n*\n$FOUND\n*\n"


OLD=$(sed -ne "/${jail_name}\ /,/^$/p" $JAIL_CONF 2>/dev/null)
NEW=$(echo "${host_jail_conf}")
if [ "$OLD" ]; then

        [ "$OLD" = "$NEW" ] && { S="Same s"; R=""; } || { S="S"; R=" or update"; }

        read -r -p "${S}ettings already exist. Do you want to remove$R the settings for $jail_name? [Y/N] " response
        case $response in
        [Yyj])
                sed -i "" "/${jail_name}/,/^$/d" $JAIL_CONF && {
                        echo "* JAIL $jail_name REMOVED"
                        [ "$OLD" = "$NEW" ] || {
                                read -p "Do you want to add the new settings for $jail_name? [Y/N] " response
                                case "$response" in
                                [Yy])
                                        echo "$host_jail_conf" >>$JAIL_CONF
                                        echo "* JAIL $jail_name UPDATED"
                                        ;;
                                esac
                        }
                }
                ;;
        [nN])
                echo "OK"
                ;;
        esac

else
        echo "$host_jail_conf" >>$JAIL_CONF
        echo "* JAIL $jail_name ADDED"
fi

Gruss, A.
 
Tja, was soll ich dazu sagen? Flutscht wie geschmiert :D
Danke vielmals :respekt:

EDIT: Noch ein kleines bisschen fine tuning
Code:
sed -i "" "/${jail_name}[B][COLOR="#FF0000"] {[/COLOR][/B]/,/^$/d" $JAIL_CONF && {
sonst wird zB. bei mysql auch mysql1 oder mysql*wasauchimmer entfernt ;)
 
Zuletzt bearbeitet:

Ähnliche Themen

Firewall regel

script mit topas ausgabe als cronjob

iptables weiterleitung port vom internen Netzwerk zum internet Port

IPTables Script - Verbessungsvorschläge?

Datei-Reader

Zurück
Oben