bash/zshでsudoから現在のセッションのfunctionを実行させる
Pocket

bashやzshでsudoを使う際、aliasは-Eでsudoに渡せるがfunctionは渡すことができない。
sudo自体にはfunctionを引き継がせるようなオプションは無く、そのままでは定義しているfunctionはsudoで実行させることができない。じゃあどうするかというと、基本的には別途そのためのfunctionを別に設定してやり、それをsudoのaliasとして定義してやる。
以下、設定のサンプル。

Sponsored Links

function SudoFunc() {
    local CMD= # 実行コマンドを取得する

    # 実行コマンドのタイプを取得する
    case $(basename ${SHELL}) in
        zsh*)
            local TYPE=$(whence -w ${CMD}|cut -d" " -f 2)
            ;;
        bash*)
            local TYPE=$(type -t ${CMD})
            ;;
    esac

    # 実行するコマンドがaliasだった場合、aliasの第一引数を取得する
    if [ ${TYPE} = "alias" ];then
        local ALIAS=$(alias ${CMD})
        local ORG_CMD=$(alias ${CMD} | sed -r "s/^alias .*='//;s/'$//g" | cut -d " " -f 1)

        # ${TYPE}を上書き
        case $(basename ${SHELL}) in
            zsh*)
                local TYPE=$(whence -w ${ORG_CMD}|cut -d" " -f 2)
                ;;
            bash*)
                local TYPE=$(type -t ${ORG_CMD})
                ;;
        esac
    else
        local ORG_CMD=${CMD}
    fi

    # TYPEをチェックし、functionだった場合はsudoで実行する
    # ※ sudoはエイリアスを読まないようにする
    if [ ${TYPE} = "function" ];then
        case ${OSTYPE} in
            darwin*)
                local DATA=$(base64 <(echo function "$(declare -f ${ORG_CMD})";echo ${ORG_CMD} ${@:2}))
                \sudo -E ${SHELL} -c "$(echo ${DATA}|base64 -D)"
                ;;
            linux*)
                local DATA=$(base64 -w 0 <(echo function "$(declare -f ${ORG_CMD})";echo ${ORG_CMD} ${@:2}))
                \sudo -E ${SHELL} -c "$(echo ${DATA}|base64 -d)"
        esac

    else
        \sudo -E "$@"
    fi
}
alias sudo='SudoFunc '

 

zshかbashか、LinuxかMacかで微妙に動きが異なるため、ちょこちょこcaseで分岐させている。一応、これでaliasに指定しているfunctionも対応できる(はず…)。
いつか、普通に何も考えずにsudoでfunctionを渡せるようになればいいのだけれど・・・(´・ω・`)。

 

Pocket

Written by blacknon

インフラエンジニア(…のつもり)。 仕事で使うならクライアントはWindowsよりはUNIXの方が好き。 大体いつも眠い。

Leave a Comment

メールアドレスが公開されることはありません。

*