ฉันมีฟังก์ชั่นทุบตีที่กำหนดไว้ในระดับโลก bashrc ซึ่งต้องใช้สิทธิ์รูทในการทำงาน ฉันจะเรียกใช้ด้วย sudo sudo myfunction
ได้อย่างไร โดยค่าเริ่มต้นจะให้ข้อผิดพลาด:
sudo: myfunction: ไม่พบคำสั่ง
ฉันมีฟังก์ชั่นทุบตีที่กำหนดไว้ในระดับโลก bashrc ซึ่งต้องใช้สิทธิ์รูทในการทำงาน ฉันจะเรียกใช้ด้วย sudo sudo myfunction
ได้อย่างไร โดยค่าเริ่มต้นจะให้ข้อผิดพลาด:
sudo: myfunction: ไม่พบคำสั่ง
คำตอบ:
Luca ได้โปรดชี้แนะให้ฉันสำหรับคำถามนี้นี่คือวิธีการของฉัน: ขยายฟังก์ชั่น / นามแฝงก่อนที่จะเรียกร้องให้ sudo และส่งต่อให้ sudo ทั้งหมดโดยไม่ต้องใช้ไฟล์ temp
อธิบายที่นี่บนบล็อกของฉัน มีการจัดการกับคำพูดมากมาย :-)
# Wrap sudo to handle aliases and functions
# Wout.Mertens@gmail.com
#
# Accepts -x as well as regular sudo options: this expands variables as you not root
#
# Comments and improvements welcome
#
# Installing: source this from your .bashrc and set alias sudo=sudowrap
# You can also wrap it in a script that changes your terminal color, like so:
# function setclr() {
# local t=0
# SetTerminalStyle $1
# shift
# "$@"
# t=$?
# SetTerminalStyle default
# return $t
# }
# alias sudo="setclr sudo sudowrap"
# If SetTerminalStyle is a program that interfaces with your terminal to set its
# color.
# Note: This script only handles one layer of aliases/functions.
# If you prefer to call this function sudo, uncomment the following
# line which will make sure it can be called that
#typeset -f sudo >/dev/null && unset sudo
sudowrap ()
{
local c="" t="" parse=""
local -a opt
#parse sudo args
OPTIND=1
i=0
while getopts xVhlLvkKsHPSb:p:c:a:u: t; do
if [ "$t" = x ]; then
parse=true
else
opt[$i]="-$t"
let i++
if [ "$OPTARG" ]; then
opt[$i]="$OPTARG"
let i++
fi
fi
done
shift $(( $OPTIND - 1 ))
if [ $# -ge 1 ]; then
c="$1";
shift;
case $(type -t "$c") in
"")
echo No such command "$c"
return 127
;;
alias)
c="$(type "$c")"
# Strip "... is aliased to `...'"
c="${c#*\`}"
c="${c%\'}"
;;
function)
c="$(type "$c")"
# Strip first line
c="${c#* is a function}"
c="$c;\"$c\""
;;
*)
c="\"$c\""
;;
esac
if [ -n "$parse" ]; then
# Quote the rest once, so it gets processed by bash.
# Done this way so variables can get expanded.
while [ -n "$1" ]; do
c="$c \"$1\""
shift
done
else
# Otherwise, quote the arguments. The echo gets an extra
# space to prevent echo from parsing arguments like -n
while [ -n "$1" ]; do
t="${1//\'/\'\\\'\'}"
c="$c '$t'"
shift
done
fi
echo sudo "${opt[@]}" -- bash -xvc \""$c"\" >&2
command sudo "${opt[@]}" bash -xvc "$c"
else
echo sudo "${opt[@]}" >&2
command sudo "${opt[@]}"
fi
}
# Allow sudowrap to be used in subshells
export -f sudowrap
ข้อเสียอย่างหนึ่งของวิธีนี้คือมันขยายฟังก์ชั่นที่คุณโทรเท่านั้นไม่ใช่ฟังก์ชั่นพิเศษใด ๆ ที่คุณอ้างอิงจากที่นั่น วิธีการของ Kyle น่าจะจัดการได้ดีกว่าถ้าคุณอ้างอิงฟังก์ชั่นที่โหลดใน bashrc ของคุณ (หากได้รับการเรียกใช้เมื่อมีการbash -c
เรียก)
คุณสามารถexport
ใช้ฟังก์ชันของคุณเพื่อให้พร้อมใช้งานสำหรับbash -c
subshell หรือสคริปต์ที่คุณต้องการใช้
your_function () { echo 'Hello, World'; }
export -f your_function
bash -c 'your_function'
แก้ไข
สิ่งนี้ใช้ได้กับ subshells โดยตรง แต่ดูเหมือนsudo
จะไม่ส่งต่อฟังก์ชั่น (ตัวแปรเท่านั้น) แม้ใช้ชุดต่างๆของsetenv
, env_keep
และกวนenv_reset
ดูเหมือนจะไม่ช่วยเหลือ
แก้ไข 2
แต่ก็ปรากฏว่าsu
ไม่สนับสนุนการส่งออกฟังก์ชั่น
your_function () { echo 'Hello, World'; }
export -f your_function
su -c 'your_function'
bash: your_function: command not found
ฉันได้รับข้อผิดพลาด ฉันใช้และUbuntu 11.04
bash shell
sudo -E bash -c 'your_function'
?
บางทีคุณสามารถทำได้:
function meh() {
sudo -v
sudo cat /etc/shadow
}
สิ่งนี้จะทำงานและช่วยคุณไม่ให้พิมพ์ sudo บน commandline
ฉันจะรันเชลล์ใหม่โดยให้ sudo รันเชลล์เองจากนั้นฟังก์ชันจะรันด้วยสิทธิ์พิเศษรูต ตัวอย่างเช่น:
vim myFunction
#The following three lines go in myFunction file
function mywho {
sudo whoami
}
sudo bash -c '. /home/kbrandt/myFunction; mywho'
root
คุณสามารถทำนามแฝงให้กับsudo bash
บรรทัดได้เช่นกัน
#!/bin/bash
function smth() {
echo "{{"
whoami
echo "}}"
}
if [ $(whoami) != "root" ]; then
whoami
echo "i'm not root"
sudo $0
else
smth
fi
เลโกลัสชี้ให้เห็นในความคิดเห็นของคำตอบของเดนนิสวิลเลียมสันคุณควรอ่านคำตอบของbmarguliesในคำถามที่คล้ายกันซึ่งโพสต์ไว้ใน stackoverflow
เริ่มต้นจากที่ฉันเขียนฟังก์ชั่นเพื่อครอบคลุมปัญหานี้ซึ่งโดยทั่วไปตระหนักถึงความคิดของ bmargulies
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
# EXESUDO
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
#
# Purpose:
# -------------------------------------------------------------------- #
# Execute a function with sudo
#
# Params:
# -------------------------------------------------------------------- #
# $1: string: name of the function to be executed with sudo
#
# Usage:
# -------------------------------------------------------------------- #
# exesudo "funcname" followed by any param
#
# -------------------------------------------------------------------- #
# Created 01 September 2012 Last Modified 02 September 2012
function exesudo ()
{
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ##
#
# LOCAL VARIABLES:
#
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ##
#
# I use underscores to remember it's been passed
local _funcname_="$1"
local params=( "$@" ) ## array containing all params passed here
local tmpfile="/dev/shm/$RANDOM" ## temporary file
local filecontent ## content of the temporary file
local regex ## regular expression
local func ## function source
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ##
#
# MAIN CODE:
#
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ##
#
# WORKING ON PARAMS:
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Shift the first param (which is the name of the function)
unset params[0] ## remove first element
# params=( "${params[@]}" ) ## repack array
#
# WORKING ON THE TEMPORARY FILE:
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
content="#!/bin/bash\n\n"
#
# Write the params array
content="${content}params=(\n"
regex="\s+"
for param in "${params[@]}"
do
if [[ "$param" =~ $regex ]]
then
content="${content}\t\"${param}\"\n"
else
content="${content}\t${param}\n"
fi
done
content="$content)\n"
echo -e "$content" > "$tmpfile"
#
# Append the function source
echo "#$( type "$_funcname_" )" >> "$tmpfile"
#
# Append the call to the function
echo -e "\n$_funcname_ \"\${params[@]}\"\n" >> "$tmpfile"
#
# DONE: EXECUTE THE TEMPORARY FILE WITH SUDO
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sudo bash "$tmpfile"
rm "$tmpfile"
}
ตัวอย่างการใช้งาน:
เรียกใช้ข้อมูลโค้ดต่อไปนี้
#!/bin/bash
function exesudo ()
{
# copy here the previous exesudo function !!!
}
test_it_out ()
{
local params=( "$@" )
echo "Hello "$( whoami )"!"
echo "You passed the following params:"
printf "%s\n" "${params[@]}" ## print array
}
echo "1: calling without sudo"
test_it_out "first" "second"
echo ""
echo "2. calling with sudo"
exesudo test_it_out -n "john done" -s "done"
exit
จะส่งออก
โทรโดยไม่มี sudo
สวัสดี yourname!
คุณผ่าน params ต่อไปนี้: วินาที
แรกโทรด้วย sudo
สวัสดีรูต!
คุณผ่าน params ต่อไปนี้:
-n
john done
-s
foo
หากคุณต้องการใช้ฟังก์ชันนี้ในเชลล์ที่เรียกใช้ฟังก์ชันซึ่งกำหนดไว้ใน bashrc ของคุณตามที่คุณถามคุณต้องใส่ฟังก์ชั่น exesudo ก่อนหน้านี้ลงในไฟล์bashrcเดียวกันเช่นกันดังนี้
function yourfunc ()
{
echo "Hello "$( whoami )"!"
}
export -f yourfunc
function exesudo ()
{
# copy here
}
export -f exesudo
จากนั้นคุณต้องออกจากระบบและลงชื่อเข้าใช้อีกครั้งหรือใช้
source ~/.bashrc
ในที่สุดคุณสามารถใช้ exesudo ดังต่อไปนี้:
$ yourfunc
Hello yourname!
$ exesudo yourfunc
Hello root!
/dev/shm/22481: No such file or directory
มา