如何使用 sudo 执行 bash 函数?

Eug*_*ash 34 bash sudo

我在全局 bashrc 中定义了一个 bash 函数,它需要 root 权限才能工作。我如何使用 sudo 运行它,例如sudo myfunction. 默认情况下,它会给出一个错误:

须藤:myfunction:找不到命令

Den*_*son 19

您可以使用export您的函数使其可用于bash -c要在其中使用它的子 shell 或脚本。

your_function () { echo 'Hello, World'; }
export -f your_function
bash -c 'your_function'
Run Code Online (Sandbox Code Playgroud)

编辑

这适用于直接子shell,但显然sudo不转发函数(仅变量)。即使使用setenv,env_keep和否定的各种组合env_reset似乎也无济于事。

编辑 2

但是,似乎su 确实支持导出的功能。

your_function () { echo 'Hello, World'; }
export -f your_function
su -c 'your_function'
Run Code Online (Sandbox Code Playgroud)

  • +1,我会说这是正确的答案。 (2认同)

wzz*_*zrd 6

也许你可以这样做:

function meh() {
    sudo -v
    sudo cat /etc/shadow
}
Run Code Online (Sandbox Code Playgroud)

这应该可以工作,并且可以让您免于在命令行上键入 sudo 。


小智 6

如果需要在 sudo 的上下文中调用函数,则需要使用declare

#!/bin/bash

function hello() {
  echo "Hello, $USER"
}

sudo su another_user -c "$(declare -f hello); hello"
Run Code Online (Sandbox Code Playgroud)


w00*_*00t 4

Luca 好心地向我指出了这个问题,这是我的方法:在调用 sudo 之前扩展函数/别名并将其完整地传递给 sudo,不需要临时文件。

在我的博客上有解释。有很多报价处理:-)

# 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
Run Code Online (Sandbox Code Playgroud)

这种方法的一个缺点是它只扩展您正在调用的函数,而不扩展您从那里引用的任何额外函数。如果您引用 bashrc 中加载的函数(假设它在调用时执行bash -c),Kyle 的方法可能会更好地处理这个问题。