Posso “exportar” funções no bash?

62
source some_file

some_file:

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

Se eu for some_file , a função "doit" e a variável TEST estarão disponíveis na linha de comando. Mas executando este script:

script.sh:

#/bin/sh
echo $TEST
doit test2

Retornará o valor de TEST, mas gerará um erro sobre a função desconhecida "doit".

Eu posso "exportar" a função também, ou eu tenho que inserir some_file no script.sh para usar a função lá?

    
por Nils 17.10.2011 / 20:44

8 respostas

90

No Bash você pode exportar definições de funções para sub-shell com

export -f function_name

Por exemplo, você pode tentar este exemplo simples:

./script1 :

    #!/bin/bash

    myfun() {
        echo "Hello!"
    }

    export -f myfun
    ./script2

./script2 :

    #!/bin/bash

    myfun

Então, se você chamar ./script1 , verá a saída Olá! .

    
por 18.10.2011 / 19:27
12

"Exportar" uma função usando export -f cria uma variável de ambiente com o corpo da função. Considere este exemplo:

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

Isso significa que somente o shell (apenas Bash?) poderá aceitar a função. Você também pode definir a função como o Bash considera apenas os envios que começam com () { como função:

$ 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'

Se você precisar "exportar" esta variável através do SSH, então você realmente precisa da função como uma string. Isso pode ser feito com a opção de impressão ( -p ) para funções ( -f ) do declare embutido:

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

Isso é muito útil se você tiver um código mais complexo que precisa ser executado sobre o SSH. Considere o seguinte roteiro fictício:

#!/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"
    
por 06.08.2014 / 15:39
5

Aproveitando a resposta de @ Lekensteyn ...

Se você usar declare -pf , todas as funções definidas anteriormente no shell atual serão enviadas para STDOUT.

Nesse ponto, você pode redirecionar o STDOUT para onde você quiser e, com efeito, colocar as funções definidas anteriormente onde você quiser.

A resposta a seguir irá preenchê-los em uma variável. Em seguida, fazemos eco dessa variável mais a invocação da função que queremos executar no novo shell que é gerado como um novo usuário. Fazemos isso usando sudo com a opção -u (também conhecido como user ) e simplesmente executando o Bash (que receberá o STDOUT canalizado como a entrada a ser executada).

Como sabemos que estamos indo de um shell Bash para um shell Bash, sabemos que o Bash interpretará corretamente as funções definidas anteriormente. A sintaxe deve estar bem, desde que nos movamos entre um shell Bash da mesma versão para um novo shell Bash da mesma versão.

YMMV se você estiver se movendo entre diferentes shells ou entre sistemas que possam ter diferentes versões do Bash.

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

FUNCTIONS='declare -pf'; echo "$FUNCTIONS ; foo" | sudo -u otheruser bash
# $./test.sh
# hello from otheruser
    
por 12.09.2014 / 02:58
3

Você não pode exportar funções, não da maneira que você está descrevendo. O shell só carregará o arquivo ~/.bashrc no início de um shell interativo (procure por "Invocação" no bash manpage ).

O que você pode fazer é criar uma "biblioteca" que é carregada quando você inicia o programa:

source "$HOME/lib/somefile"

E coloque suas funções e configurações não interativas lá.

    
por 17.10.2011 / 20:58
1

As funções não são exportadas para subprocessos. É por isso que existem arquivos chamados .kshrc ou .bashrc: Para definir funções que também estão disponíveis em sub-unidades.

Se estiver executando um script, os scripts * shrc normalmente não são originados. Você teria que codificar isso explicitamente, como em . ~/.kshrc .

    
por 17.10.2011 / 20:57
1

eval "$(declare -F | sed -e 's/-f /-fx /')" exportará as todas funções.

Eu faço muito isso antes de iniciar um shell interativo em um script para permitir que eu depure e trabalhe no contexto do script enquanto uso suas funções e variáveis.

Exemplo:

eval "$(declare -F | sed -e 's/-f /-fx /')"
export SOME IMPORTANT VARIABLES AND PASSWORDS
bash -i
    
por 04.05.2017 / 16:48
0

Bem, sou novo no Linux, mas você pode tentar isso. Em algum arquivo, vamos chamá-lo, 'tmp / general' você constrói sua função:

func1(){
   echo "func from general"
}

Em seu script de shell, adicione:

. /tmp/general

e execute:

func1

Você vai aparecer na tela: func from general .

    
por 28.01.2014 / 17:41
0
declare -x -f NAME

Mais informações

-f        restrict action or display to function names and definitions
-x        to make NAMEs export
    
por 04.11.2014 / 20:30

Tags