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

Problème de script avec une console.

11 réponses
Avatar
Dominique
Bonjour,
J'ai écrit un petit script qui monte un disque dur externe, ouvre une
console et me positionne à la racine du DD. Je voudrais, en plus, qu'il
m'affiche, dans la foulée, un ls -l.
Voilà mon script :

#!/bin/bash
mount /mnt/hd
konsole --workdir /mnt/hd --noclose -e ls -l

Je monte mon HD, j'ouvre une console, mon ls -l est bien affiché... mais la
console est gelée, je ne peux rien en faire sauf la fermer !

Quel conseil pourriez-vous me donner ?
Bonne soirée,
Dominique

10 réponses

1 2
Avatar
Bruno Mathieu
Dominique a écrit:

#!/bin/bash
mount /mnt/hd
konsole --workdir /mnt/hd --noclose -e ls -l


konsole, c'est une application kde => x11.

Je monte mon HD, j'ouvre une console, mon ls -l est bien affiché... mais
la console est gelée, je ne peux rien en faire sauf la fermer !

Quel conseil pourriez-vous me donner ?


Perso, je modifierais le $HOME/.bashrc pour quelque chose d'approchant.
Tu ajoutes tes 2 dernières lignes à la fin du fichier $HOME/.bashrc.
Mais là, à chaque ouverture d'un shell tu montes le périphérique...


Bonne soirée,


--
Bruno

Avatar
Dominique
Bruno Mathieu wrote:

konsole, c'est une application kde => x11.


Exact.

Mais là, à chaque ouverture d'un shell tu montes le périphérique...


C'est ce que je voudrais éviter. Je ne souhaite monter mon disque qu'à la
demande.
Bonne soirée,
Dominique

Avatar
Nicolas George
Rakotomandimby Mihamina wrote in message
:
Tu peux nous donner la syntaxe que la doc propose pour l'argument après
'-e' ?


C'est certainement la même que pour xterm, à savoir la liste des arguments à
passer à l'appel système exec.

Parceque tu peux par exemple faire un '-e (ls -l ; /bin/sh)' , ce qui te
donnerai un prompt directement après le 'ls -l'.


Il y a très peu de chances que ça marche. En revanche, ceci marchera
certainement :

-e sh -c 'ls -l; exec $SHELL'

Avatar
Rakotomandimby Mihamina
On Sun, 31 Oct 2004 15:44:27 +0100, Bruno Mathieu wrote:

Dominique a écrit:

#!/bin/bash
mount /mnt/hd
konsole --workdir /mnt/hd --noclose -e ls -l



Tu peux nous donner la syntaxe que la doc propose pour l'argument après
'-e' ?

Parceque tu peux par exemple faire un '-e (ls -l ; /bin/sh)' , ce qui te
donnerai un prompt directement après le 'ls -l'.

Mais ça dépend de la syntaxe.
--
ASPO Infogérance - http://aspo.rktmb.org/activites/infogerance
Unofficial FAQ fcolc - http://faq.fcolc.eu.org/
Linux User Group sur Orléans et alentours.
Tél: + 33 2 38 76 43 65 (France)


Avatar
Bruno Mathieu
Dominique a écrit:

Bruno Mathieu wrote:

konsole, c'est une application kde => x11.


Exact.

Mais là, à chaque ouverture d'un shell tu montes le périphérique...


C'est ce que je voudrais éviter. Je ne souhaite monter mon disque qu'à la
demande.


Dans $HOME.bashrc, tu encapsule tes lignes dans un if

if [ O$TOTO == O ]; then ...; fi

Ensuite tu crées un fichier "lien vers une appli" dans kde, avec la
propriété Commande : "TOTO=x konsole" Ça passera la variable TOTO à
l'environnement et en fonction tu fais ce que tu veux.

Bonne soirée,
Dominique


Bonne soirée.
--
Bruno


Avatar
Dominique
Rakotomandimby Mihamina wrote:

Tu peux nous donner la syntaxe que la doc propose pour l'argument après
'-e' ?
konsole --help :


-e <command> Exécute «command» à la place du shell


Parceque tu peux par exemple faire un '-e (ls -l ; /bin/sh)' , ce qui te
donnerai un prompt directement après le 'ls -l'.


Ca a l'air de lui faire tout drôle (hd, c'est le nom de mon script) :

[ messcripts]$ ./hd
./hd: line 3: syntax error near unexpected token `('
./hd: line 3: `konsole --workdir /mnt/hd -e (ls -l ; /bin/sh)'

Visiblement, le bash n'aime pas les parenthèses.


Mais ça dépend de la syntaxe.


C'est sûr. Je ne dois pas être loin de la solution mais je ne la vois pas.
Si je remplace les parenthèses par des guillements, il y a un Fail exec et
ma console est plantée.

Merci,
Dominique

Avatar
Dominique
Nicolas George wrote:


Il y a très peu de chances que ça marche. En revanche, ceci marchera
certainement :

-e sh -c 'ls -l; exec $SHELL'


Et ça marche même très bien ! Merci. J'ai ma réponse.
Est-ce que tu pourrais m'expliquer pourquoi cette ligne marche et pourquoi
mes essais, eux, ne marchaient pas ?

Dominique

Avatar
Vincent Bernat
OoO Lors de la soirée naissante du dimanche 31 octobre 2004, vers
17:26, Bruno Mathieu disait:

if [ O$TOTO == O ]; then ...; fi


On préférera :

if [[ -z $TOTO ]]; then ... ; fi
--
panic("esp_handle: current_SC == penguin within interrupt!");
2.2.16 /usr/src/linux/drivers/scsi/esp.c

Avatar
Bruno Mathieu
Vincent Bernat a écrit:

if [ O$TOTO == O ]; then ...; fi


On préférera :

if [[ -z $TOTO ]]; then ... ; fi


Merci Vincent, j'oublie à chaque fois et je fais la sale méthode :-/
L'avantage de la solution de Nicolas (sh -c 'ls -l; exec $SHELL') est
qu'elle est quand même plus portable que mon brouillon !

--
Bruno


Avatar
Nicolas George
Dominique wrote in message <41851b5a$0$3672$:
Et ça marche même très bien ! Merci. J'ai ma réponse.
Est-ce que tu pourrais m'expliquer pourquoi cette ligne marche et pourquoi
mes essais, eux, ne marchaient pas ?


Pas de problème, mais il faut partir des bases. Quand un programme est
lancé, il s'agit d'un chemin vers un binaire, plus une liste d'arguments qui
sont des chaînes de caractères, brutes et sans interprétation. C'est l'appel
système execve qui fait ça. Tout ce qui est spécial dans une ligne de
commande est fait par le shell. Ainsi, quand on tape :

rm *.mp3; ls *.ogg

le shell fait ceci successivement :

- il détecte le point-virgule, caractère spécial, et coupe la ligne en
deux ;

- il détecte l'espace après rm, et le prend comme la séparation entre le nom
de la commande et un argument ;

- il détecte l'étoile, et remplace *.mp3 par la liste des fichier reconnus ;

- il cherche rm dans le PATH ;

- il exécute la commande ainsi construite, qui va être quelque chose comme,
en notation C :

execl("/bin/rm", "rm", "foo.mp3", "bar.mp3", "baz.mp3", NULL);

[cf les remarques à la fin] ;

- il attend que la commande se termine ;

- il détecte l'espace après ls ;

- il remplace *.ogg par la liste des fichiers reconnus ;

- il cherche ls dans le PATH ;

- il exécute :

execl("/bin/ls", "ls", "foobar.ogg", "bazqux.ogg", NULL);

- il attend que la commande se termine.

[remarques :

- execl est une fonction pratique par rapport à execve qui accepte ses les
arguments de la commande directement dans la liste des arguments, avec
NULL pour marquer la fin. Normalement, avec execve, il faut construire
un tableau et passer un pointeur sur ce tableau (et passer un pointeur
sur le tableau de l'environnement également). D'ailleurs, un shell va
systématiquement utiliser execve plutôt qu'execl, puisqu'il doit
construire le tableau des arguments à l'exécution.

- Par convention, toutes les commandes reçoivent en premier argument le
nom de la commande, ce qui explique pourquoi la commande a à la fois
/bin/rm et rm. La plupart du temps, elles l'ignorent simplement, mais
certaines adaptent leur comportement, comme gzip, qui compresse quand
son premier argument est gzip, et décompresse quand il est gunzip.

Maintenant, que fait xterm, ou konsole ? Il ouvre une fenêtre, exécute une
commande en établissant un canal de communication (un pseudo-terminal) avec
elle, affiche tout ce que lui dit la commande, et transmet à la commande ce
que l'utilisateur tape au clavier. Quand la commande se termine, xterm se
ferme.

Quelle commande est exécutée ? Par défaut, c'est le contenu de la variable
d'environnement $SHELL, sans arguments supplémentaires. Normalement, ça
correspond à un programme qui affiche un prompt, lit des commandes et les
exécute, un shell interactif.

Mais ça peut être changé par l'option -e. Que prend l'option -e ? Pas une
vraie ligne de commande, car il faudrait embarquer un shell dans xterm, ce
qui serait lourd et pénible. Au contraire, xterm prend ce qui suit -e comme
une liste d'arguments constituant une ligne de commande déjà construite.
Ainsi, si l'on tape :

xterm -e vim *.tex

xterm verra ces arguments-là, passés par le shell où on a tapé ça :

xterm -e vim foo.tex bar.tex

et exécutera :

vim foo.tex bar.tex

Ce qui est exactement ce qu'on attendait de lui. Mais ça marche parce que
l'étoile a un comportement sympa de ce point de vue. Si on écrit ceci :

xterm -e vim foo.tex; latex foo.tex

alors le shell découpe la ligne au point-virgule avant de considérer la
commande xterm, puis il exécute :

xterm -e vim foo.tex

et xterm ne voit jamais le point-virgule. D'ailleurs, il n'aurait pas su
quoi en faire. Si on essaie, par exemple :

xterm -e vim foo.tex ';' latex foo.tex

pour forcer le point-virgule à être passé à xterm, alors xterm va exécuter

execl("/usr/bin/vim", "vim", "foo.tex", ";", "latex", "foo.tex", NULL);

c'est à dire lancer vim sur le fichier foo.tex (deux fois), le fichier
latex, et le fichier « ; ».

On ne peut pas en sortir, xterm ne sait exécuter qu'un seul programme.
Cependant, on peut en sortir, il suffit de faire un script. Si on colle dans
un script :

#!/bin/sh
vim foo.tex
latex foo.tex

et qu'on lance

xterm -e ./ce_script

alors xterm exécute ce script, un seul programme, et c'est ce script (en
fait, un /bin/sh qui est en train de l'interpréter) qui lui-même exécute
successivement vim et latex.

On peut faire l'économie du fichier pour le script si on sait que la plupart
des shells, dont sh, savent prendre en argument une ligne de commande qu'ils
doivent décomposer de manière habituelle et exécuter; C'est l'option qui
fait ça. Donc plutôt que de faire un script, on peut taper :

xterm -e sh -c 'vim foo.tex; latex foo.tex'

Maintenant, le but initial, c'était d'avoir ls, puis une invite de commande,
et pas vim puis latex. ls, ben c'est ls, l'invite de commande, c'est $SHELL
(souvent /bin/bash sous Linux, on se demande pourquoi, et en tout cas ce
n'est pas systématiquement ça, donc il vaut mieux utiliser $SHELL). Donc ça
devient :

xterm -e sh -c 'ls; $SHELL'

Reste le petit détail : l'exec :

xterm -e sh -c 'ls; exec $SHELL'

Il dit au sh qui est en train de faire le -c qu'il ne doit pas lancer $SHELL
dans un nouveau processus, mais l'exécuter à la place de lui-même. Ainsi, au
lieu d'avoir :

- xterm - xterm
_ sh -c puis _ sh -c
_ ls _ $SHELL

on a :

- xterm - xterm
_ sh -c puis _ $SHELL
_ ls

Ça économise de la mémoire et du CPU (et c'est aussi mieux pour des
histoires de sessions de processus, mais je ne vais pas en parler).

Quant à la version avec les parenthèses, la parenthèse est un caractère
spécial pour beaucoup de shell, qui ne peut pas se placer n'importe où.

1 2