web-dev-qa-db-fra.com

Puis-je "exporter" des fonctions en bash?

source some_file

some_file:

doit ()
{
  echo doit $1
}
export TEST=true

Si je source some_file la fonction "doit" et la variable TEST sont disponibles sur la ligne de commande. Mais en exécutant ce script:

script.sh:

#/bin/sh
echo $TEST
doit test2

Renvoie la valeur de TEST, mais génère une erreur sur la fonction inconnue "doit".

Puis-je "exporter" la fonction aussi, ou dois-je me procurer un fichier dans script.sh pour y utiliser la fonction?

96
Nils

Dans Bash, vous pouvez exporter des définitions de fonctions vers un sous-shell avec

export -f function_name

Par exemple, vous pouvez essayer cet exemple simple:

./script1:

    #!/bin/bash

    myfun() {
        echo "Hello!"
    }

    export -f myfun
    ./script2

./script2:

    #!/bin/bash

    myfun

Ensuite, si vous appelez ./script1 vous verrez la sortie Bonjour!.

142
enzotib

"Exporter" une fonction à l'aide de export -f crée une variable d'environnement avec le corps de la fonction. Considérez cet exemple:

$ fn(){ echo \'\"\ \ \$; }
$ export -f fn
$ sh -c printenv\ fn
() {  echo \'\"\ \ \$
}

Cela signifie que seul le Shell (juste Bash?) Pourra accepter la fonction. Vous pouvez également définir la fonction vous-même car le Bash ne considère que les envvars commençant par () { comme fonction:

$ fn2='() { echo Hi;}' sh -c fn2
Hi
$ fn3='() {' sh -c :
sh: fn3: line 1: syntax error: unexpected end of file
sh: error importing function definition for `fn3'

Si vous devez "exporter" cette variable sur SSH, vous avez vraiment besoin de la fonction sous forme de chaîne. Cela peut être fait avec l'option d'impression (-p) pour les fonctions (-f) du declare intégré:

$ declare -pf fn
fn () 
{ 
    echo \'\"\ \ \$
}

Ceci est très utile si vous avez du code plus complexe qui doit être exécuté via SSH. Considérez le script fictif suivant:

#!/bin/bash
remote_main() {
   local dest="$HOME/destination"

   tar xzv -C "$dest"
   chgrp -R www-data "$dest"
   # Ensure that newly written files have the 'www-data' group too
   find "$dest" -type d -exec chmod g+s {} \;
}
tar cz files/ | ssh user@Host "$(declare -pf remote_main); remote_main"
18
Lekensteyn

S'appuyant sur @ réponse de Lekensteyn ...

Si tu utilises declare -pf il affichera toutes les fonctions précédemment définies dans le shell actuel vers STDOUT.

À ce stade, vous pouvez rediriger STDOUT où vous le souhaitez et, en fait, remplir les fonctions précédemment définies où vous le souhaitez.

La réponse suivante les placera dans une variable. Ensuite, nous faisons écho à cette variable plus l'invocation de la fonction que nous voulons exécuter dans le nouveau shell qui est généré en tant que nouvel utilisateur. Pour ce faire, nous utilisons Sudo avec le -u (aka. user) et simplement lancer Bash (qui recevra le STDOUT canalisé comme entrée à exécuter).

Comme nous savons que nous allons d'un shell Bash à un shell Bash, nous savons que Bash interprétera correctement les fonctions définies par les shells précédents. La syntaxe devrait être correcte tant que nous passons d'un shell Bash de la même version à un nouveau shell Bash de la même version.

YMMV si vous vous déplacez entre différents shells ou entre des systèmes qui peuvent avoir différentes versions de Bash.

#!/bin/bash
foo() {
  echo "hello from `whoami`"
}

FUNCTIONS=`declare -pf`; echo "$FUNCTIONS ; foo" | Sudo -u otheruser bash
# $./test.sh
# hello from otheruser
8
Jesse

Vous ne pouvez pas exporter de fonctions, pas de la manière que vous décrivez. Le shell ne chargera que le ~/.bashrc fichier au début d'un shell interactif (recherchez "Invocation" dans la page de manuel bash ).

Ce que vous pouvez faire est de créer une "bibliothèque" qui sera chargée au démarrage du programme:

source "$HOME/lib/somefile"

Et placez-y vos fonctions et paramètres non interactifs.

5
Arcege

eval "$(declare -F | sed -e 's/-f /-fx /')" exportera toutes les fonctions.

Je le fais beaucoup avant de démarrer un shell interactif dans un script pour me permettre de déboguer et de travailler dans le contexte du script tout en utilisant ses fonctions et ses variables.

Exemple:

eval "$(declare -F | sed -e 's/-f /-fx /')"
export SOME IMPORTANT VARIABLES AND PASSWORDS
bash -i
2
Schlomo

Les fonctions ne sont pas exportées vers des sous-processus. C'est pourquoi il existe des fichiers nommés .kshrc ou .bashrc: pour définir des fonctions qui devraient également être disponibles en sous-coquilles.

Si vous exécutez un script, les scripts. * Shrc ne sont normalement pas fournis. Vous devez coder cela explicitement, comme dans . ~/.kshrc.

1
ktf
declare -x -f NAME

Plus d'informations

 - f restreindre l'action ou l'affichage aux noms et définitions des fonctions 
 - x pour faire exporter les NOMS 
1
Steven Penny

Eh bien, je suis nouveau sur Linux, mais vous pouvez essayer cela. Dans un fichier, appelons-le, 'tmp/general' vous construisez votre fonction:

func1(){
   echo "func from general"
}

Dans votre script Shell, ajoutez:

. /tmp/general

et courir:

func1

Vous obtiendrez à l'écran: func from general.

1
noone