OVH Cloud OVH Cloud

read sous Linux

11 réponses
Avatar
Michele
Bonjour,

Soit le script suivant :
#!/bin/ksh
PATH=/usr/bin:/bin:/sbin:......
uname -a | read val1 val2 other

Sous solaris, le script fonctionne bien, et les variables val1 val2 et other
sont bien renseignées.
Alors que sous Linux (RedHat Enterprise 3.0 AS), les variables val1, val2 et
other ne sont pas renseignées. Alors que "uname -a" tout seul affiche bien
quelque chose.

De même, toujours sous Linux, si je mets dans le script :
uname -a > /tmp/fic.txt
read val1 val2 other < /tmp/fic/txt

Les variables val1, val2 et other sont bien renseignées.
Quelqu'un aurait-il une explication ?

Et comment écrire le script de façon optimale et portable (fonctionnant sous
Linux et Solaris) pour affecter les variables val1, val2 et other avec le
contenu de uname -a ?

Merci d'avance.

10 réponses

1 2
Avatar
Jean-Louis Liagre
Michele wrote:
Bonjour,

Soit le script suivant :
#!/bin/ksh
PATH=/usr/bin:/bin:/sbin:......
uname -a | read val1 val2 other

Sous solaris, le script fonctionne bien, et les variables val1 val2 et other
sont bien renseignées.
Alors que sous Linux (RedHat Enterprise 3.0 AS), les variables val1, val2 et
other ne sont pas renseignées. Alors que "uname -a" tout seul affiche bien
quelque chose.

De même, toujours sous Linux, si je mets dans le script :
uname -a > /tmp/fic.txt
read val1 val2 other < /tmp/fic/txt

Les variables val1, val2 et other sont bien renseignées.
Quelqu'un aurait-il une explication ?

Et comment écrire le script de façon optimale et portable (fonctionnant sous
Linux et Solaris) pour affecter les variables val1, val2 et other avec le
contenu de uname -a ?

Merci d'avance.


Le problème ne vient pas directement de Solaris ou Linux, mais des
shells utilisés qui sont différents.

Il n'y a pas de ksh en standard sous Linux, il y a pdksh ou bash,
qui ni l'un ni l'autre ne gèrent correctement cette syntaxe, car
les read se fait dans un sous-shell et les variables sont perdues.

Une solution consiste à installer le vrai ksh (ksh93) qui est en
open source, disponible sur la page de son auteur (David Korn):
http://www.kornshell.com/

Sinon, une solution portable ksh/pdksh/bash:

read val1 val2 <<%
$(uname -a)
%

Avatar
Nicolas George
Jean-Louis Liagre wrote in message
<42d2faea$0$4268$:
Une solution consiste à installer le vrai ksh (ksh93) qui est en
open source, disponible sur la page de son auteur (David Korn):
http://www.kornshell.com/


Tant qu'à faire, autant installer zsh, qui a en plus de bonnes chances
d'être packagé.

Avatar
Stephane Chazelas
2005-07-12, 00:14(+02), Michele:
Soit le script suivant :
#!/bin/ksh
PATH=/usr/bin:/bin:/sbin:......
uname -a | read val1 val2 other

Sous solaris, le script fonctionne bien, et les variables val1 val2 et other
sont bien renseignées.
Alors que sous Linux (RedHat Enterprise 3.0 AS), les variables val1, val2 et
other ne sont pas renseignées.


Elles sont renseignees mais dans un sous-shell qui ne fait
qu'executer la commande read.

Alors que "uname -a" tout seul affiche bien
quelque chose.


Dans cmd1 | cmd2

Il y a besoin de deux processus puisqu'ils sont lancés en
parallele.

dans

builtin1 | builtin2

Il n'y a pas de garantie que ce soit builtin1 ou builtin2 qui
soit donc lancé dans un sous shell. C'est aux developpeurs du
shell de choisir.

De même, toujours sous Linux, si je mets dans le script :
uname -a > /tmp/fic.txt
read val1 val2 other < /tmp/fic/txt

Les variables val1, val2 et other sont bien renseignées.
Quelqu'un aurait-il une explication ?


Pas de pipe -> pas de processus en parallele -> pas de
sous-shell. Avec le Bourne shell (comme le /bin/sh de Solaris),
redirection implique sous-shell, je ne sais pas si ca s'applique
a read toutefois dans les Bourne shell plus /recents/.


Et comment écrire le script de façon optimale et portable (fonctionnant sous
Linux et Solaris) pour affecter les variables val1, val2 et other avec le
contenu de uname -a ?


Deja, eviter ksh, utiliser sh (le POSIX)

#! /bin/sh -

# work around to get a POSIX sh on Solaris:
false ^ true && [ -x /usr/xpg4/bin/sh ] &&
exec /usr/xpg4/bin/sh - "$0" ${1+"$@"}
# work around to get POSIX utilities on Solaris (please blame
# Sun)
PATH=$(command -p getconf PATH; :)$PATH
export PATH

set -f
set -- $(uname -a)
val1=$1
val2=$2
...

ou

uname -a | {
read -r val1 val2
quelque chose avec "$val1" "$val2"
}

--
Stéphane

Avatar
Jean-Louis Liagre
Nicolas George wrote:
Jean-Louis Liagre wrote in message

Une solution consiste à installer le vrai ksh (ksh93) qui est en
open source, disponible sur la page de son auteur (David Korn):
http://www.kornshell.com/



Tant qu'à faire, autant installer zsh, qui a en plus de bonnes chances
d'être packagé.


Sauf que zsh risque d'etre moins compatible avec ksh que ... ksh.


Avatar
Stephane Chazelas
On Tue, 12 Jul 2005 15:28:49 +0200, Jean-Louis Liagre wrote:
Nicolas George wrote:
Jean-Louis Liagre wrote in message

Une solution consiste à installer le vrai ksh (ksh93) qui est en
open source, disponible sur la page de son auteur (David Korn):
http://www.kornshell.com/



Tant qu'à faire, autant installer zsh, qui a en plus de bonnes chances
d'être packagé.


Sauf que zsh risque d'etre moins compatible avec ksh que ... ksh.


"ksh" est une vue de l'esprit. Il y a des douzaines de versions
parmi lesquelles pdksh et zsh en ksh emulation et toutes les
versions par Korn/Bell/AT&T (de ksh88 a ksh88i dont les sources
ne sont pas disponibles, tous les ksh93 jusqu'a ksh93q avec
aucun suivi rigoureux des modifications et truffés de bugs sans
compter les diverses modifications des differents vendeurs Unix
et les differentes derivations comme dtksh...).

Eviter la programmation ksh. Utiliser une syntaxe POSIX de
shell comme compromis. Si ce n'est pas suffisant, c'est qu'il
faut utiliser un vrai language de programmation (perl, python,
ruby par exemple pour les interpretés).

(a noter que bash est globalement un clone non fini de ksh avec
la plupart de ses erreurs de design).

--
Stephane



Avatar
Jean-Louis Liagre
Stephane Chazelas wrote:
On Tue, 12 Jul 2005 15:28:49 +0200, Jean-Louis Liagre wrote:

Nicolas George wrote:

Jean-Louis Liagre wrote in message


Une solution consiste à installer le vrai ksh (ksh93) qui est en
open source, disponible sur la page de son auteur (David Korn):
http://www.kornshell.com/



Tant qu'à faire, autant installer zsh, qui a en plus de bonnes chances
d'être packagé.


Sauf que zsh risque d'etre moins compatible avec ksh que ... ksh.



"ksh" est une vue de l'esprit.


ksh n'est pas une vue de l'esprit, c'est le shell développé par David
Korn.

Il y a des douzaines de versions
parmi lesquelles pdksh et zsh en ksh emulation


Ce ne sont pas des versions de ksh, mais des clones.

et toutes les
versions par Korn/Bell/AT&T (de ksh88 a ksh88i dont les sources
ne sont pas disponibles, tous les ksh93 jusqu'a ksh93q avec
aucun suivi rigoureux des modifications et truffés de bugs


"Truffés" est peut-être un peu fort ...

sans
compter les diverses modifications des differents vendeurs Unix


Les vendeurs d'Unix corrigent les bugs, je ne connais pas d'ajout
de fonctionnalités apportés par des vendeurs, mais je peux me
tromper.

et les differentes derivations comme dtksh...).


et tksh, mais ils sont restés assez confidentiels.

Eviter la programmation ksh.


Je ne vois pas pourquoi.

Utiliser une syntaxe POSIX de
shell comme compromis. Si ce n'est pas suffisant, c'est qu'il
faut utiliser un vrai language de programmation (perl, python,
ruby par exemple pour les interpretés).


ksh est un "vrai" langage de programmation.

(a noter que bash est globalement un clone non fini de ksh avec
la plupart de ses erreurs de design).


qui sont ?




Avatar
Stephane Chazelas
On Tue, 12 Jul 2005 18:20:35 +0200, Jean-Louis Liagre wrote:
[...]
Utiliser une syntaxe POSIX de
shell comme compromis. Si ce n'est pas suffisant, c'est qu'il
faut utiliser un vrai language de programmation (perl, python,
ruby par exemple pour les interpretés).


ksh est un "vrai" langage de programmation.
[...]


Si tu veux poursuivre la discussion, je te suggere de partir de
la:

http://groups-beta.google.com/group/comp.unix.shell/browse_frm/thread/ef6413c44adef728/98578e8d95137a3c

ainsi que la suite du thread, ou j'ai deja exprimé en parti ce
que je pensais de ksh et de la programmation shell en general.

N'hesite pas a poursuivre la discussion ici, si tu n'es pas
d'accord avec ce qui y est dit (lire tout le thread avant).

--
Stephane


Avatar
Michele
Je vais essayer de transformer le script en sh. Est-ce que le script
ci-dessous vous semble juste ?
Peut-on l'améliorer ?
Ce script étant destiné à tourner sous Solaris et sous Linux.
Et s'il était en ksh (en remplaçant #!bin/sh par #!/bin/ksh), comment
l'écrire ?
D'autre part, s'il y avait une autre astuce pour récupérer les champs de
"uname -a" que par "set - `uname -a`" ? Car j'ai un peu peur d'utiliser $1
$2 qui écrasent ceux passés au script.

#!/bin/sh

PATH=:/bin:/usr/bin:/sbin:/usr/sbin

case ="$1" in
=-c)
_TRC="+"
_NUM="$2"
shift 2
;;
=)
exit 0
;;
=-*)
exit 1
;;
=*)
_TRC="="
;;
esac
[ -z "$2" ] || exit 2
_DATE=`date +'%Y/%m/%d %H:%M:%S'`
_TAB=" "

set - `uname -a`
_OS=$1
_MACH=$2
_RL=$3
_OTHERS=$4

_USR="$USER"
[ -z "$_USR" ] && _USR="$LOGNAME"
[ -z "$_USR" ] && _USR="$(/usr/bin/id)" && _USR="${_USR#*(} &&
_USR="${_USR%%)*}"

echo "$_TRC
$_DATE$_TAB$_USR$_TAB$_MACH$_TAB$DISPLAY$_TAB$_OS$_TAB$_RL$_TAB$_NUM" |
autre_commande

exit 0

Merci d'avance.

"Stephane Chazelas" a écrit dans le message
news:
On Tue, 12 Jul 2005 18:20:35 +0200, Jean-Louis Liagre wrote:
[...]
Utiliser une syntaxe POSIX de
shell comme compromis. Si ce n'est pas suffisant, c'est qu'il
faut utiliser un vrai language de programmation (perl, python,
ruby par exemple pour les interpretés).


ksh est un "vrai" langage de programmation.
[...]


Si tu veux poursuivre la discussion, je te suggere de partir de
la:


http://groups-beta.google.com/group/comp.unix.shell/browse_frm/thread/ef6413

c44adef728/98578e8d95137a3c

ainsi que la suite du thread, ou j'ai deja exprimé en parti ce
que je pensais de ksh et de la programmation shell en general.

N'hesite pas a poursuivre la discussion ici, si tu n'es pas
d'accord avec ce qui y est dit (lire tout le thread avant).

--
Stephane




Avatar
Jean-Louis Liagre
Michele wrote:
...
D'autre part, s'il y avait une autre astuce pour récupérer les champs de
"uname -a" que par "set - `uname -a`" ? Car j'ai un peu peur d'utiliser $1
$2 qui écrasent ceux passés au script.


Il y a surement plus simple, mais voilà une méthode qui passe sous Solaris
et Linux:

#!/bin/sh
eval `uname -a | awk '
{
print "_OS="$1
print "_MACH="$2
print "_RL="$3
for (i = 4; i <= NF; i++ )
if(i==4) x=$i
else x=x " " $i
print "_OTHER=""x"""
}'`

Avatar
Christophe Blaess
D'autre part, s'il y avait une autre astuce pour récupérer les champs de
"uname -a" que par "set - `uname -a`" ? Car j'ai un peu peur d'utiliser $1
$2 qui écrasent ceux passés au script.


Une solution : sauvegarder les arguments avant d'appeler "set",
puis les récupérer ensuite.

En voici un exemple testé avec Bash, mais je pense qu'il doit
fonctionner sur tout shell Posix :

#! /bin/sh

i=0
for arg in "$@"; do
sauve[$i]="$arg"
i=$((i+1))
done

set - $(uname -a)

systeme="$1"
nom="$2"
version="$3"

set - "${sauve[@]}"

echo "systeme = $systeme"
echo "version = $version"

echo '$1 = ' $1
echo '$2 = ' $2
echo '$@ = ' $@

Et un exemple d'exécution montrant que l'on récupère bien les
arguments initiaux (même s'ils contiennent des espaces) :

$ ./script.sh "ABC DEF" GHI JKL
systeme = Linux
version = 2.4.19
$1 = ABC DEF
$2 = GHI
$@ = ABC DEF GHI JKL
$


--
Christophe Blaess
http://www.blaess.fr/christophe/

1 2