Przekazać funkcję innemu użytkownikowi w Bash?

11

Czy jest jakiś sposób na przekazanie funkcji od jednego użytkownika do drugiego?

Na przykład mam mały skrypt Bash, który wykonuję jako root:

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

Jednak funkcja user_func nie jest zdefiniowana dla użytkownika Vagrant, tylko dla rootowania i nie może zostać wykonana.

Inną opcją byłoby posiadanie wielu linii

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

Lub, wykonaj wiele poleceń np .: su vagrant -c 'cmd1; cmd2; cmd3;', ale wolałbym nie mieć nadmiaru, szczególnie gdy próbujesz wykonać więcej niż 5 poleceń jako użytkownik Vagrant.

Czy można przekazać funkcję innemu użytkownikowi z tego samego skryptu (np. Nie tworząc skryptu na dysku jako inny użytkownik, a następnie wykonując wygenerowany skrypt)? Czy jest jeszcze inna opcja, którą przeoczam?

gdieckmann
źródło

Odpowiedzi:

10

Wygląda na to, że musisz exportnajpierw zdefiniować tę funkcję:

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

powinien załatwić sprawę.

-fMówi export, że jest to nazwa funkcji, a nie nazwa zmiennej. Cytowanie z help export:

Zaznacza każdą NAZWĘ do automatycznego eksportu do środowiska później wykonywanych poleceń. …

Opcje:

 -f   refer to shell functions

Jak zauważyli Peterph i Stephane w komentarzach, zakłada to dwie rzeczy:

  1. Twoje supolecenie nie zastąpi środowiska użytkownika
  2. To vagrantjest powłoka logowania bash. Jeśli nie, możesz użyć alternatywnego suwiersza poleceń udostępnionego przez Stephane:

    su vagrant -c 'bash -c user_func'
Joseph R.
źródło
Właśnie na to liczyłem. Nie zdawałem sobie sprawy, że możesz wyeksportować tę funkcję. Działa to tak, jak miałem nadzieję po edycji przykładowego skryptu. Dzięki!
gdieckmann
1
Fajnie, ale nie działa w przypadkach, w których suprzesłania środowisko.
peterph
1
Zauważ, że działa to tylko wtedy, gdy powłoka logowania vagrantto bash. Jeśli nie,su vagrant -c 'bash -c user_func'
Stéphane Chazelas,
6

Jest to trochę hackerskie, ale możesz wydrukować definicję funkcji w przekazanej sommandzie sui wtedy możesz oczywiście jej użyć.

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

Działa to nawet, jeśli z jakiegoś powodu środowisko spawnowanej powłoki suzostanie nadpisane, ponieważ umieszcza definicję po inicjalizacji powłoki. Jeśli napiszesz funkcję wystarczająco kompatybilnie, zadziała nawet wtedy, gdy dwóch użytkowników, o których mowa, używa różnych powłok.

Peter
źródło
+1 Naprawdę fajna sztuczka! Tylko pytanie, czy środowisko supowłoki może zostać zastąpione przez czynniki zewnętrzne? Mam na myśli, że w tym przypadku masz pełną kontrolę nad suwierszem poleceń, ponieważ jest on w skrypcie. Jak można zastąpić środowisko nowej powłoki?
Joseph R.
Na przykład powłoka spawnowana przez sumoże dokonać inicjalizacji środowiska. Również susam może usunąć część środowiska dzwoniącego, aby nieco zwiększyć bezpieczeństwo (chociaż zwykle dzieje się tak dzięki bardziej wydajnym alternatywom, takim jak sudo).
peterph
0

Nie masz takiego skryptu, to funkcja. Wygląda na to, że potrzebujesz skryptu. Stwórz odpowiedni skrypt i umieść go, zgodnie z własnymi potrzebami, w /usr/local/binlub w /home/vagrant/bin, a następnie powinieneś być w stanie npsu vagrant -c '/home/vagrant/bin/myscript.sh'

DopeGhoti
źródło
Jest to funkcja w przykładowym skrypcie. Miałem nadzieję, że w tym jednym skrypcie będę zawierał wszystko, co chcę zrobić (polecenia uruchamiane jako root i użytkownik Vagrant), i nie będę musiał mieć osobnego skryptu dla użytkownika root i osobnego skryptu dla użytkownika Vagrant.
gdieckmann
0

Innym, nieco bardziej przenośnym sposobem, aby to zrobić (bez zależności bash) jest wywołanie skryptu przez siebie i zmiana zachowania w zależności od kontekstu (UID) lub parametrów. przykłady tego podano w dokumentacji, w superktórej pokazują skrypt, który wymaga uprawnień roota, wywołując siebie poprzez super, gdy nie jest rootem.

Hildred
źródło