Can I "export" functions in bash?
source some_file
some_file:
doit ()
{
echo doit $1
}
export TEST=true
If I source some_file the function “doit” and the variable TEST are available on the command line. But running this script:
script.sh:
#/bin/sh
echo $TEST
doit test2
Will return the value of TEST, but will generate an error about the unknown function “doit”.
Can I “export” the function, too, or do I have to source some_file in script.sh to use the function there?
Functions are not exported to subprocesses. This is why there are files named .kshrc or .bashrc: To define functions that shoiuld be available in subshells also.
If running a script, the .*shrc scripts are normally not sourced. You would have to code that explicitly, like in . ~/.kshrc
.
You cannot export functions, not in the way that you are describing. The shell will only load the ~/.bashrc
file on the start of an interactive shell (search for “Invocation” in the bash manpage).
What you can do is create “library” which is loaded when you start the program:
source "$HOME/lib/somefile"
And place your non-interactive functions and settings there.
In Bash you can export function definitions to other shell scripts that your script calls with
export -f function_name
For example you can try this simple example:
./script1
:
#!/bin/bash
myfun() {
echo "Hello!"
}
export -f myfun
./script2
./script2
:
#!/bin/bash
myfun
Then if you call ./script1
you will see the output Hello!.
Well, I’m new to Linux, but you can try this. In some file, let’s call it, ‘tmp/general’ you build your function:
func1(){
echo "func from general"
}
In your shell script add:
. /tmp/general
and run:
func1
You’ll get on the screen: func from general
.
“Exporting” a function using export -f
creates an environment variable with the function body. Consider this example:
$ fn(){ echo '" $; }
$ export -f fn
$ sh -c printenv fn
() { echo '" $
}
This means that only the shell (just Bash?) will be able to accept the function. You could also set the function yourself as the Bash only considers envvars starting with () {
as function:
$ 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'
If you need to “export” this variable over SSH, then you really need the function as a string. This can be done with the print option (-p
) for functions (-f
) of the declare
built-in:
$ declare -pf fn
fn ()
{
echo '" $
}
This is very useful if you have more complex code that needs to be executed over SSH. Consider the following fictitious script:
#!/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"
Building on @Lekensteyn’s answer…
If you use declare -pf
it will output all the previously defined functions in the current shell to STDOUT.
At that point you can redirect STDOUT to wherever you want and in effect stuff the previously defined functions wherever you want.
The following answer will stuff them into a variable. Then we echo that variable plus the invocation of the function that we want to run into the new shell that is spawned as a new user. We do this by using sudo
with the -u
(aka. user
) switch and simply running Bash (which will receive the piped STDOUT as the input to run).
As we know that we are going from a Bash shell to a Bash shell we know that Bash will interpret the previous shells defined functions correctly. The syntax should be fine as long as we are moving between one Bash shell of the same version to a new Bash shell of the same version.
YMMV if you are moving between different shells or between systems that may have different versions of Bash.
#!/bin/bash
foo() {
echo "hello from `whoami`"
}
FUNCTIONS=`declare -pf`; echo "$FUNCTIONS ; foo" | sudo -u otheruser bash
# $./test.sh
# hello from otheruser
declare -x -f NAME
More info
-f restrict action or display to function names and definitions -x to make NAMEs export
eval "$(declare -F | sed -e 's/-f /-fx /')"
will export all functions.
I do this a lot before starting an interactive shell in a script to enable me to debug and work in the script context while using its functions and variables.
Example:
eval "$(declare -F | sed -e 's/-f /-fx /')"
export SOME IMPORTANT VARIABLES AND PASSWORDS
bash -i