Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

shell : repasser les arguments d'un script en variable POST via curl

18 réponses
Avatar
Francois Lafont
Bonsoir à tous,

Je suis confronté à un problème de script shell dont
je pensais de prime abord que j'allais en venir à
bout relativement facilement mais finalement je coince
complètement... peut-être parce que je suis passé à
côté d'un truc simple. Je ne sais pas.

J'ai un script qui reçoit des arguments en ligne de
commandes. Par exemple :

./mon-script "arg1" "aaa aa" "bbbb"

Le nombre d'arguments n'est pas constant à chaque appel.
C'est toujours au moins 1 mais à part ça on ne rien
supposer (des fois ce sera 3, d'autres fois 10 etc).

Je voudrais que le script lance un curl sur une page
en localhost en passant ses arguments en variables
POST comme ceci :

curl -d "token1=arg1" -d "token2=aaa aa" -d "token3=bbbb" http://localhost/ma-page
# la variable POST token1 contient le premier paramètre du script.
# la variable POST token2 contient le deuxième paramètre du script.
# etc.

Si par exemple le script était appelé avec systématiquement
3 arguments, alors je pense qu'il me suffirait de coder le
script comme ceci :

-------------------------------------------------------
#!/bin/sh

curl -d "token1=$1" -d "token2=$2" -d "token3=$3" http://localhost/ma-page
-------------------------------------------------------

Seulement, comme je l'ai indiqué plus haut, le nombre d'arguments
n'est pas forcément constant. Il y a donc une sorte de boucle
à mettre en place ici mais là je coince complètement. Au départ,
j'ai pensé à ça :

-------------------------------------------------------
#!/bin/sh

i=1
for arg in "$@"
do
options="$options -d token$i=$arg"
i=$((i+1))
done

curl $options http://localhost/ma-page
-------------------------------------------------------

Mais le script se vautre lamentablement dès qu'un argument
possède un espace. Dans le cas de mon exemple précédent, c'est
le curl suivant qui serait appelé :

curl -d token1=arg1 -d token2=aaa aa -d token3=bbbb http://localhost/ma-page
^^^^^^^^

Or, les paramètres peuvent potentiellement contenir des
espaces (et d'autres caractères « exotiques »). Je souhaiterais
pouvoir faire cela avec le shell sh de ma Debian Wheezy.
Est-ce que vous voyez un moyen de le faire ?

Merci d'avance pour vos éventuelles pistes.

--
François Lafont

8 réponses

1 2
Avatar
Francois Lafont
Le 06/07/2014 10:49, Nicolas George a écrit :
Francois Lafont , dans le message
<53b8aafb$0$2213$, a écrit :
arg=$(printf "%s" "$arg" | sed "s/'/$replace_quote/g")



Et les guillemets doubles ? Et les dollars ? Et les backslashes ? Et les
backquotes ?



J'ai re-vérifié, normalement mon script « résiste » à tous ces
caractères. Bon, ceci étant, le passage multiple des sed est
une vrai catastrophe au niveau perf.

Il me semble qu'en Perl j'en serais réduit aux
même genre de contorsions mais je me trompe peut-être.



Tu te trompes. Perl, contrairement au shell, a des tableaux à part entière.
Et peut évidemment invoquer une commande avec sa liste d'arguments précise
sans invoquer un shell intermédiaire.



Avec la fonction system(), c'est ça ?

Par curiosité, est-ce qu'on peut me confirmer (ou m'infirmer) ceci :

1. avec system() en Perl, on ne peut pas récupérer la sortie de la
commande invoquée ?

2. si on souhaite récupérer (toujours en Perl) la sortie de la commande
invoquée, alors le seul moyen est d'utiliser les backquotes `` et dans
ce cas, c'est forcément une chaîne de caractères qu'il faut fournir dans
les `` et la commande est forcément invoquée via un shell ?

Si cette dernière phrase te semble le moins du monde obscure, c'est que tu
n'as pas encore assez bien compris le principe de lancement d'un processus
Unix pour pouvoir mener à bien ta tâche, et je t'invite à lire en détail la
page de man d'excve(2).



Je suppose qu'il s'agit de execve(2). Je lirai cette page man avec
grand intérêt. Merci.

--
François Lafont
Avatar
Nicolas George
Francois Lafont , dans le message
<53b94c4e$0$1981$, a écrit :
J'ai re-vérifié, normalement mon script « résiste » à tous ces
caractères.



Avec l'eval à la fin de ce que tu as montré, ça m'étonnerait grandement.

Avec la fonction system(), c'est ça ?



Sa forme à plusieurs arguments. Ou l'équivalent plus bas niveau exec() en
gérant les processus explicitement.

1. avec system() en Perl, on ne peut pas récupérer la sortie de la
commande invoquée ?



Pas directement, en effet.

2. si on souhaite récupérer (toujours en Perl) la sortie de la commande
invoquée, alors le seul moyen est d'utiliser les backquotes `` et dans
ce cas, c'est forcément une chaîne de caractères qu'il faut fournir dans
les `` et la commande est forcément invoquée via un shell ?



Non, ce n'est pas le seul moyen. On peut tout aussi facilement le faire avec
open($fh, "-|", @cmd).

Je suppose qu'il s'agit de execve(2).



Oui, dsol pour la faut d frapp.
Avatar
Francois Lafont
Le 06/07/2014 10:52, Nicolas George a écrit :
Francois Lafont , dans le message
<53b8a92b$0$2267$, a écrit :
1. Il est appelé avec des paramètres.
2. Il retransmet ces paramètres en variables POST via
un curl à destination d'une page http qui lance un
script Perl justement (et le script Perl utilisera
ces variables POST pour faire son travail).



Ces deux arguments abondent dans mon sens : il faut utiliser un vrai langage
de script.



Oui et c'est ce que je fais globalement avec les scripts Perl.
Mais il y a un point sur lequel je ne me suis pas encore
expliqué et quitte a donner le contexte, autant aller jusqu'au
bout.

Le travail des checks est fait par du Perl via Apache et
mod_perl. Mais je ne peux pas invoquer directement mes checks
via un curl sur les scripts Perl. En effet, dans un check, il
faut une sortie (par exemple « DISK OK - free space: / 3326
MB (56%) ») mais il faut que le check renvoie un exit code
spécifique qui indique l'état de ce qu'on veut checker :

- 0 si tout est OK
- 1 si on a un WARNING
- 2 si on a un CRITICAL
- 3 si l'état n'est un des cas précédents (ça s'appelle UNKNOWN)

Du coup, un curl direct sur mes checks en Perl ne convient pas,
car, en considérant que Apache+mod_perl fonctionnent bien, le
curl renverra 0 systématiquement, quelque soit le résultat du
check (que celui-ci soit en OK ou en CRITICAL etc). C'est pourquoi
j'ai besoin d'un lanceur/wrapper qui va faire un curl mais qui
devra aussi analyser la sortie du curl. Plus exactement le curl
(ie le check Perl invoqué) renverra 2 lignes comme ceci :

1
DISK WARNING - free space: / 3326 MB (10%)

où la première ligne est le exit code du check
et la deuxième sera la sortie du check.
Donc le lanceur/wrapper devra afficher la deuxième
ligne du curl et renvoyer comme exit code la valeur
indiquée dans la première ligne du curl.

Voilà pourquoi j'ai besoin d'un lanceur/wrapper qui
fait un chouilla plus qu'un simple curl car il me
faut renvoyer un exit code spécifique.

Seulement, il me faut
un lanceur qui déclenche les checks, ie un programme assez
trivial qui reçoit les arguments dont le check a besoin



Dans ce cas, arrange-toi pour que les arguments en question soient formés
exclusivement de caractères alphanumériques, inertes pour le shell.

Et sinon, passe au C.



Hélas mes compétences en C sont nulles. Mais c'est
vrai que ça serait l'idéal.


--
François Lafont
Avatar
Nicolas George
Francois Lafont , dans le message
<53b972f7$0$3620$, a écrit :
Voilà pourquoi j'ai besoin d'un lanceur/wrapper qui
fait un chouilla plus qu'un simple curl car il me
faut renvoyer un exit code spécifique.



Toutes tes explications sont bonnes et belles, mais elles n'ont strictement
rien à voir avec la discussion en cours.

Toutes tes interventions poussent à une seule conclusion : tu cherches à
courir avant de savoir marcher.
Avatar
Francois Lafont
Le 06/07/2014 15:24, Nicolas George a écrit :

J'ai re-vérifié, normalement mon script « résiste » à tous ces
caractères.



Avec l'eval à la fin de ce que tu as montré, ça m'étonnerait grandement.



J'ai vraiment essayé des appels avec des trucs affreux,
je n'ai pas réussi à mettre en défaut le script. Si tu
as un exemple d'appel où ça ne fonctionne pas, je serais
curieux de le connaître.

Avec la fonction system(), c'est ça ?



Sa forme à plusieurs arguments. Ou l'équivalent plus bas niveau exec() en
gérant les processus explicitement.

1. avec system() en Perl, on ne peut pas récupérer la sortie de la
commande invoquée ?



Pas directement, en effet.

2. si on souhaite récupérer (toujours en Perl) la sortie de la commande
invoquée, alors le seul moyen est d'utiliser les backquotes `` et dans
ce cas, c'est forcément une chaîne de caractères qu'il faut fournir dans
les `` et la commande est forcément invoquée via un shell ?



Non, ce n'est pas le seul moyen. On peut tout aussi facilement le faire avec
open($fh, "-|", @cmd).



Ok, merci.

Je suppose qu'il s'agit de execve(2).



Oui, dsol pour la faut d frapp.



Pas de souci. ;)


--
François Lafont
Avatar
Michel
Le 06/07/2014 19:07, Nicolas George a écrit :
Francois Lafont , dans le message
<53b972f7$0$3620$, a écrit :
Voilà pourquoi j'ai besoin d'un lanceur/wrapper qui
fait un chouilla plus qu'un simple curl car il me
faut renvoyer un exit code spécifique.



Toutes tes explications sont bonnes et belles, mais elles n'ont strictement
rien à voir avec la discussion en cours.

Toutes tes interventions poussent à une seule conclusion : tu cherches à
courir avant de savoir marcher.




Il est vrai que tes interventions sont toujours aussi constructives !
Avatar
Francois Lafont
Le 06/07/2014 19:07, Nicolas George a écrit :

Toutes tes explications sont bonnes et belles, mais elles n'ont strictement
rien à voir avec la discussion en cours.



Oui, c'est vrai, désolé.

Toutes tes interventions poussent à une seule conclusion : tu cherches à
courir avant de savoir marcher.



Sans doute. Je vais en rester là pour la partie digression
de ce fil et tenter de me documenter davantage.

Merci pour ton aide.

--
François Lafont
Avatar
Francois Lafont
Le 06/07/2014 12:47, Fred a écrit :

Tu peux aussi reprendre cette commande avec autant de token qu'il peut
y avoir d'arguments. Au pire, les derniers tokens seront vide mais
comme ta page doit analyser les arguments qu'elle reçoit, ce ne sera
pas un problème.



Oui, c'est une option en effet. Cela signifie qu'il
faut que je choisisse plus ou moins arbitrairement
un nombre maximum de tokens, suffisamment grand pour
que je sois sûr qu'aucun appel ne dépasse ce nombre
de token.

--
François Lafont
1 2