OVH Cloud OVH Cloud

La redirection qui patine

7 réponses
Avatar
Jeannot Lelapin
Bonjour à tous,

je souhaite rediriger l'affichage d'un fichier sur gawk.
Ma ligne de commande est la suivante:
cat MyLogFile.txt | gawk '/ERROR/ { print $0 }'
Ca marche comme je veux.

J'ai besoin de faire un cat parce qu'après je vais le remplacer par tail
-f dans un script ou je choisis la commande cat ou tail -f.

Et c'est justement avec un script que tout merde.

----------------------
SCRIPT BEGIN
----------------------

#!/bin/bash

# Mes variables
COMMAND=cat
PATTERN="gawk '/ERROR/ { print \$0 }'"

# J'obtiens exactement la ligne de commande que
# j'ai tapé directement dans le shell
echo "${COMMAND} MyLogFile | $PATTERN"

${COMMAND} MyLogFile | $PATTERN

----------------------
SCRIPT END
----------------------

à l'exécution, j'obtiens systématiquement
gawk: cmd. line:1: '/ERROR/
gawk: cmd. line:1: ^ invalid char ''' in expression

J'ai cherché dans tous les sens. Je n'y comprends plus rien.

Ca doit être une toute petite bétise. Quelqu'un peut m'aider ?

Cordialement,

Jeannot

7 réponses

Avatar
Stephane CHAZELAS
Le Sun, 12 Oct 2003 11:51:00 +0200, Jeannot Lelapin écrivait :
je souhaite rediriger l'affichage d'un fichier sur gawk.
Ma ligne de commande est la suivante:
cat MyLogFile.txt | gawk '/ERROR/ { print $0 }'


ou:

cat MyLogFile.txt | gawk '/ERROR/'

ou

cat MyLogFile.txt | grep ERROR

[...]
#!/bin/bash

# Mes variables
COMMANDÊt
PATTERN="gawk '/ERROR/ { print $0 }'"
[...]

${COMMAND} MyLogFile | $PATTERN
[...]

à l'exécution, j'obtiens systématiquement
gawk: cmd. line:1: '/ERROR/
gawk: cmd. line:1: ^ invalid char ''' in expression
[...]


Ben oui forcément. À l'expansion de $PATTERN, le shell fait du
découpage (et eventuellement de la filename generation) pas de
l'interprétation de code shell.

PATTERN="gawk '/ERROR/ { print $0 }'"
$PATTERN

ça lance gawk avec comme arguments:

argv[0]="gawk"
argv[1]="'/ERROR/"
argv[2]="{"
argv[3]="print"
...

Alors qu'il faudrait que ce soit:

argv[0]="gawk"
argv[1]="/ERROR/ {print $0}"


Soit tu fais:

IFS="|"; set -f
PATTERN='gawk|/ERROR/ {print $0}'
COMMAND='tail|-f'

$COMMAND MyLogFile | $PATTERN


soit tu fais (bash specific):

COMMAND=(tail -f)
PATTERN=(gawk '/ERROR/ {print $0}')

"${COMMAND[@]}" MyLogFile | "${PATTERN[@]}"

soit tu fais:

COMMAND() {
tail -f "$@"
}
PATTERN() {
gawk '/ERROR/ {print $0}' "$@"
}

COMMAND MyLogFile | PATTERN

soit tu fais:

COMMAND="tail -f"
PATTERN="gawk '/ERROR/ {print $0}'"

eval "$COMMAND MyLogFile" | eval "$PATTERN"

eval est là pour interpréter du code shell.
Voir "info bash"

--
Stéphane

Avatar
Jeannot Lelapin
Merci pour ta réponse et tes explications.

Je suis finalement arrivé à mes fins avec la première solution.

Mon script maintenant complet permet de filtrer mes logs comme je le
souhaite. Il est certe rudimentaire car je ne maitrise absolument pas
les regexp, sed,... Il faudra de toute façon que je m'y mette.
Je débute aussi dans l'écriture des scripts shell et en bash.

Cordialement,

Jeannot

=========================================== LogAnalyser.sh
=========================================== #!/bin/bash

# 2003.10.12
# L'analysis d'un fichier de log générée avec log4cpp
# Le script est basé sur la recherche des mots clés :
# EMERG, FATAL, ALERT, CRIT, ERROR, WARN, NOTICE, INFO, DEBUG, NOTSET

# Le paramètre 1 : le nom du fichier à analyser
# Le paramètre 2 : l'utilisation de cat ou tail
# pour tail, l'option -f est rajoutée
# Le paramètre 3 : le niveau de trace recherché ( les traces de priorité
# supérieure à celles choisies sont elle aussi affichées )

# La vérification du nombre d'arguments
if ! [ $(($#)) == 3 ] ; then
echo "FAILURE : LogAnalyser.sh cat/tail priority filename"
exit 1
fi

# La vérification de la présence du fichier à analyser
if ! [ -f $1 ] ; then
echo "FAILURE : $1 doesn't exist"
exit 1
fi

# La vérification de la possibilité de lecture du fichier à analyser
if ! [ -r $1 ] ; then
echo "FAILURE : $1 isn't available for reading"
exit 1
fi

# La vérification du mode choisi
case "$2" in
cat)
COMMAND='cat'
;;
tail)
COMMAND='tail§-f'
;;
*)
echo "FAILURE : arg 2 : $1 doesn't match cat or tail"
exit 1
;;
esac

# La vérification de la priorité recherchée
case "$3" in
NOTSET)
PATTERN='gawk§/NOTSET/ || /DEBUG/ || /INFO/ || /NOTICE/ || /WARN/
|| /ERROR/ || /CRIT/ || /ALERT/ || /FATAL/ || /EMERG/ {print $0}'
;;
DEBUG)
PATTERN='gawk§/DEBUG/ || /INFO/ || /NOTICE/ || /WARN/ || /ERROR/
|| /CRIT/ || /ALERT/ || /FATAL/ || /EMERG/ {print $0}'
;;
INFO)
PATTERN='gawk§/INFO/ || /NOTICE/ || /WARN/ || /ERROR/ || /CRIT/ ||
/ALERT/ || /FATAL/ || /EMERG/ {print $0}'
;;
NOTICE)
PATTERN='gawk§/NOTICE/ || /WARN/ || /ERROR/ || /CRIT/ || /ALERT/
|| /FATAL/ || /EMERG/ {print $0}'
;;
WARN)
PATTERN='gawk§/WARN/ || /ERROR/ || /CRIT/ || /ALERT/ || /FATAL/ ||
/EMERG/ {print $0}'
;;
ERROR)
PATTERN='gawk§/ERROR/ || /CRIT/ || /ALERT/ || /FATAL/ || /EMERG/
{print $0}'
;;
CRIT)
PATTERN='gawk§/CRIT/ || /ALERT/ || /FATAL/ || /EMERG/ {print $0}'
;;
ALERT)
PATTERN='gawk§/ALERT/ || /FATAL/ || /EMERG/ {print $0}'
;;
FATAL)
PATTERN='gawk§/FATAL/ || /EMERG/ {print $0}'
;;
EMERG)
PATTERN='gawk§/EMERG/ {print $0}'
;;
*)
echo "FAILURE : arg 3 : $3 doesn't match NOTSET, DEBUG, INFO,
NOTICE, WARN, ERROR, CRIT, ALERT, FATAL, EMERG "
exit 1
;;
esac

IFS="§"; set -f

# L'exécution de la commande
$COMMAND $1 | $PATTERN
Avatar
Jeannot Lelapin
J'ai fait un deuxième script pour compter le nombre de processus que je
recherche en mémoire


#!/bin/bash
PROCESSCOUNT=`ps -ef | grep 'java -jar' | grep -v grep | wc -l`
echo "PROCESSCOUNT : $PROCESSCOUNT"

==>> Il marche



!/bin/bash
JAVAPROC='java -jar'
PROCESSCOUNT=`ps -ef | grep $JAVAPROC | grep -v grep | wc -l`
echo "PROCESSCOUNT : $PROCESSCOUNT"

==> les résultat du lancement du script
grep: option invalide -- j
Usage: grep [OPTION]... PATRON [FICHIER]...
Pour en savoir davantage, faites: `grep --help'.
PROCESSCOUNT : 0


#!/bin/bash
IFS="§"; set -f
JAVAPROC='java -jar'
PROCESSCOUNT=`ps -ef | grep $JAVAPROC | grep -v grep | wc -l`
echo "PROCESSCOUNT : $PROCESSCOUNT"

==>> Il marche

Il y a certainement d'autres manières de faire, je vais y arriver.

Merci encore,

Jeannot
Avatar
Stephane CHAZELAS
Le Sun, 12 Oct 2003 13:30:15 +0200, Jeannot Lelapin écrivait :
[...]
!/bin/bash
JAVAPROC='java -jar'
PROCESSCOUNT=`ps -ef | grep $JAVAPROC | grep -v grep | wc -l`
echo "PROCESSCOUNT : $PROCESSCOUNT"

==> les résultat du lancement du script
grep: option invalide -- j
[...]


Il s'agit du "découpage" ou "word splitting" dont je parlais
dans mon autre message.

PROCESSCOUNT=`ps -ef | grep -- "$JAVAPROC" | grep -cv grep`

ou mieux:

PROCESSCOUNT=$(ps -eo args= | grep -c '[j]ava -jar')

--
Stéphane

Avatar
Stephane CHAZELAS
Le Sun, 12 Oct 2003 13:27:01 +0200, Jeannot Lelapin écrivait :
[...]
if ! [ $(($#)) == 3 ] ; then


if [ "$#" -ne 3 ]

ou (bash/ksh93/zsh specific)

if (( $# != 3 )); then

echo "FAILURE : LogAnalyser.sh cat/tail priority filename"


echo >&2 "FAILURE : LogAnalyser.sh cat/tail priority filename"

[...]
if ! [ -f $1 ] ; then


if [ ! -f "$1" ]; then


if ! [ -r $1 ] ; then


if [ ! -r "$1" ]; then


case "$2" in
cat)
COMMAND='cat'
;;
tail)
COMMAND='tail§-f'
;;
*)
echo "FAILURE : arg 2 : $1 doesn't match cat or tail"
exit 1
;;
esac

# La vérification de la priorité recherchée
case "$3" in
NOTSET)
PATTERN='gawk§/NOTSET/ || /DEBUG/ || /INFO/ || /NOTICE/ || /WARN/
|| /ERROR/ || /CRIT/ || /ALERT/ || /FATAL/ || /EMERG/ {print $0}'
;;
DEBUG)
PATTERN='gawk§/DEBUG/ || /INFO/ || /NOTICE/ || /WARN/ || /ERROR/
[...]


J'aurais trouvé plus lisible:

followúlse
case "$1" in
"-f") follow=true
shift;;
esac
if [ "$#" -ne 2 ]; then
echo >&2 'Usage: ${0##*/} [-f] priority filename'
exit 1
fi

case $1 in
NOTSET) PATTERN="
NOTSET
DEBUG
INFO
NOTICE
WARN
..." ;;
...) ;;
esac

if "$follow"; then
tail -f -- "$2" | grep -e "$PATTERN"
else
grep -e "$PATTERN" < "$2"
fi

Ou encore:

PATTERN=$(sed -e "/$1/q" << EOF
EMERG
FATAL
ALERT
CRIT
ERROR
WARN
NOTICE
INFO
DEBUG
NOTSET
)

qui te remplace ton gros "case".

--
Stéphane

Avatar
Stephane CHAZELAS
Le 12 Oct 2003 12:44:42 GMT, Stephane CHAZELAS écrivait :
[...]
PATTERN=$(sed -e "/$1/q" << EOF
EMERG
FATAL
ALERT
CRIT
ERROR
WARN
NOTICE
INFO
DEBUG
NOTSET
)


Ou encore, en évitant sed et un fichier temporaire:

ALL="
EMERG
FATAL
ALERT
CRIT
ERROR
WARN
NOTICE
INFO
DEBUG
NOTSET
"

case $ALL in
*"
$1
"*) PATTERN="${ALL%"
$1
"*}
$1"
PATTERN=${PATTERN#?};;
*) printf >&2 'Unknown priority: "%s"n' "$1"
exit 1;;
esac


grep -e "$PATTERN" < "$2"

Avec bash/ksh93/zsh, tu peux l'écrire plus lisiblement:

case $ALL in
*$'n'"$1"$'n'*)
PATTERN=${ALL%$'n'"$1"$'n'*}$'n'$1
PATTERN=${PATTERN#$'n'};;
*) printf >&2 'Unknown priority: "%s"n' "$1"
exit 1;;
esac

--
Stéphane

Avatar
Jeannot Lelapin
Merci Stéphane pour toutes réponses et ces pistes.
Je vais m'y mettre au regexp, sed et le shell bien compris.

Jeannot