Передать функцию другому пользователю в Bash?


11

Можно ли как-то передать функцию от одного пользователя другому?

Например, у меня есть небольшой скрипт Bash, который я выполняю как Root:

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

Однако функция user_func не определена для пользователя Vagrant, только для Root, и не может быть выполнена.

Мой другой вариант будет иметь несколько строк

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

Или выполнить несколько команд ex:, su vagrant -c 'cmd1; cmd2; cmd3;'но я бы предпочел, чтобы их не было, особенно при попытке выполнить более 5 команд в качестве пользователя Vagrant.

Можно ли передать функцию другому пользователю из того же сценария (например, не создавать сценарий на диске как другой пользователь, а затем выполнять этот созданный сценарий)? Или есть другой вариант, который я пропускаю?

Ответы:


10

Похоже, вам нужно exportсначала определить это определение функции:

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

должен сделать свое дело.

The -fговорит, exportчто это имя функции, а не имя переменной. Цитирование из help export:

Отмечает каждое ИМЯ для автоматического экспорта в среду последующих выполненных команд. ....

Параметры:

 -f   refer to shell functions

Как отмечают Петерф и Стефан в комментариях, это предполагает две вещи:

  1. Что ваша suкоманда не будет перезаписывать среду пользователя
  2. Это vagrantлогин оболочки bash. Если нет, вы можете использовать альтернативную suкомандную строку, предоставленную Stephane:

    su vagrant -c 'bash -c user_func'

На самом деле это именно то, на что я надеялся. Я не понимал, что вы сможете экспортировать функцию. Это сработало так же, как я надеялся после редактирования примера сценария. Благодарность!
gdieckmann

1
Хорошо, но не сработает в тех случаях, когда suпереопределяет окружение.
Петер

1
Обратите внимание, что это работает только в том случае, если оболочкой входа vagrantявляется bash. Если нет,su vagrant -c 'bash -c user_func'
Стефан Шазелас

6

Это немного хакерски, но вы можете напечатать определение функции внутри передаваемой соманды, suа затем, конечно, можете ее использовать.

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

Это сработает, даже если по какой-то причине среда оболочки, suкоторая была создана, будет перезаписана, так как она помещает определение после инициализации оболочки. Если вы напишите функцию достаточно совместимо, она будет работать даже тогда, когда два пользователя используют разные оболочки.


+1 Действительно изящный трюк! Только вопрос, может ли suсреда оболочки быть перезаписана внешними факторами? Я имею в виду, что в этом случае вы имеете полный контроль над suкомандной строкой, поскольку она находится в сценарии. Как можно перезаписать среду его новой оболочки?
Джозеф Р.

Например, созданная оболочка suможет выполнить некоторую инициализацию окружения. Также suсамо по себе может лишить некоторые среды вызывающего абонента, чтобы немного повысить безопасность (хотя это обычно делается с помощью более мощных альтернатив, таких как sudo).
Петер

0

Это не скрипт, а функция. Похоже, вы хотите сценарий, хотя. Создайте правильный сценарий и поставьте его, как того требуют ваши потребности, как в /usr/local/bin, так и в /home/vagrant/bin, и чем вы сможете, например,su vagrant -c '/home/vagrant/bin/myscript.sh'


Это функция в примере сценария. Я надеялся включить в этот единственный сценарий все, что я хочу сделать (команды запускаются как Root и как пользователь Vagrant), и не нужно было иметь отдельный скрипт для пользователя Root и отдельный скрипт для пользователя Vagrant.
gdieckmann

0

Другой более переносимый способ сделать это (без зависимости от bash) - заставить ваш скрипт вызывать себя и изменять свое поведение в зависимости от контекста (uid) или параметров. примеры этого приведены в документации, superгде показан скрипт, которому требуются права суперпользователя, который вызывает себя с помощью super, когда не root.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.