Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Is there any way that I can pass a Function from one user to another user?

For example, I have a small Bash script that I execute as Root:

#!/bin/bash
user_func(){
  whoami
  exit
}
su vagrant -c 'user_func'

However, the user_func Function isn't defined for the Vagrant user, only for Root, and can't be executed.

My other option would be to have multiple lines of

su vagrant -c 'cmd1' 
su vagrant -c 'cmd2'
, etc 

Or, execute multiple commands ex: su vagrant -c 'cmd1; cmd2; cmd3;', but I'd prefer to not have the excess, especially when attempting to execute more than 5 commands as the Vagrant user.

Is it possible to pass a Function to another user from within the same script (ex. not creating a script on disk as a different user and then executing that generated script)? Or is there another option that I am overlooking?

share|improve this question
add comment

4 Answers

up vote 7 down vote accepted

Sounds like you need to export that function definition first:

#!/bin/bash
user_func (){
  whoami
  exit
}
export -f user_func
su vagrant -c 'user_func'

should do the trick.

The -f tells export that this is a function name rather than a variable name. Quoting from help export:

Marks each NAME for automatic export to the environment of subsequently executed commands. ....

Options:

 -f   refer to shell functions

As pointed out by peterph and Stephane in the comments, this assumes two things:

  1. That your su command will not overwrite the user's environment
  2. That vagrant's login shell is bash. If not, you can use the alternative su command line provided by Stephane:

    su vagrant -c 'bash -c user_func'
    
share|improve this answer
    
This is actually exactly what I was hoping for. I didn't realize that you would be able to export the function. This worked just as I was hoping it would after editing the sample script. Thanks! –  gdieckmann Dec 23 '13 at 21:48
1  
Nice, but won't work in cases where su overrides the environment. –  peterph Dec 23 '13 at 21:51
1  
Note that it only works if the login shell of vagrant is bash. If not, su vagrant -c 'bash -c user_func' –  Stephane Chazelas Dec 23 '13 at 21:58
add comment

It's a bit hackish, but you can print the definition of the function inside the sommand passed to su and then you can of course use it.

$ function foo { do_some_stuff_here; }
$ su test -c "$(typeset -f foo); foo"

This will work even if for some reason the environment of the shell spawned by su will be overwritten, since it puts the definition after shell initialization. If you write the function compatibly enough, it will even work when the two users in question are using different shells.

share|improve this answer
    
+1 Really neat trick! Just a question though, can the su shell's environment be overwritten by external factors? I mean, in this case you have complete control over the su command line since it's in a script. How can its new shell's environment be overwritten? –  Joseph R. Dec 23 '13 at 21:48
    
For example the shell spawned by su might do some initialization of environment. Also su itself might strip some of the caller's environment to tighten security a bit (although this is usually done by more powerful alternatives like sudo). –  peterph Dec 23 '13 at 22:04
    
I see. Thanks for the info. –  Joseph R. Dec 23 '13 at 22:05
add comment

That's not a script you have, it's a function. It sounds like you want a script, though. Make a proper script and put it, as your needs require, either in /usr/local/bin, or in /home/vagrant/bin, and than you should be able to e. g. su vagrant -c '/home/vagrant/bin/myscript.sh'

share|improve this answer
    
It's a function within a sample script. My hope was to include everything that I want to do within this single script (commands run as Root, and as the Vagrant user), and not have to have a separate script for the Root user and a separate script for the Vagrant user. –  gdieckmann Dec 23 '13 at 21:37
add comment

Another somewhat more portable way to do this (no bash dependency) Is to have your script call its self and have its behavior change based on either context (uid) or parameters. examples of this are given in the documentation for super where they show a script that needs root permissions, calling its self through super when not root.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.