web-dev-qa-db-ja.com

〜/ .zshrcから関数をSudoするときに「コマンドが見つかりません」

~/.zshrcに関数があります:

findPort() {
    lsof -t -i :$1
}

通常の呼び出しはfindPort 3306です。

昇格した権限で実行したい。しかし、「コマンドが見つかりません」と表示されます。

➜  git ???? Sudo findPort 3306
Sudo: findPort: command not found

その理由は、rootユーザーが非対話型シェルとして実行されている(したがって、.zshrcを参照していない)か、または別の.zshrcを参照しているためだと思います。

aliasに関する同様の質問を見ましたが、ユーザー定義関数に関する質問はありません。 aliasに関するこの問題の回答には、~/.zshrcへのエイリアスの追加が含まれます。

alias Sudo='nocorrect Sudo '

多分:

alias Sudo='Sudo '

私はこれらの両方の解決策を試しましたが、問題はまだ存在しています(はい、シェルを再起動しました)。

また、ルートシェルがzshで実行されるように、Sudo chshを実行してみました。これらの解決策はいずれも「コマンドが見つかりません」の問題を取り除きません。

Sudoでユーザー定義関数を実行する方法はありますか?

10
Birchlabs

Sudoは、シェルを介さずに直接コマンドを実行します。そのコマンドを実行するためにシェルを実行した場合でも、それは新しいシェルの呼び出しであり、_~/.zshrc_を読み取るものではありません(インタラクティブなシェルを開始した場合でも、 rootを_~/.zshrc_変数をリセットしないように構成していない限り、おそらくSudoの_$HOME_を読み取るでしょう。

ここでは、Sudoに新しいzshシェルを開始するように指示し、そのzshにその関数を実行する前に_~/.zshrc_を読み取るように指示する必要があります。

_Sudo zsh -c '. $0; "$@"' ~/.zshrc findPort 3306
_

または:

_Sudo zsh -c '. $0; findPort 3306' ~/.zshrc
_

または、現在のzsh関数をzshによって呼び出される新しいSudoと共有するには:

_Sudo zsh -c "$(functions); findPort 3306"
_

多くの関数が定義されている場合(補完システムを使用する場合など)、arg list too longエラーが発生する可能性があります。したがって、これをfindPort関数(および、関数が依存している他のすべての関数)に制限することができます。

_Sudo zsh -c "$(functions findPort); findPort 3306"
_

あなたも行うことができます:

_Sudo zsh -c "(){$functions[findPort]} 3306"
_

findPort関数のコードを3306引数を渡す無名関数に埋め込むにはあるいは:

_Sudo zsh -c "$functions[findPort]" findPort 3306
_

(_-c_ is関数の本体に渡されるインラインスクリプト)。

次のようなヘルパー関数を使用できます。

_zsudo() Sudo zsh -c "$functions[$1]" "$@"
_

使ってはいけません:

sdo(){Sudo zsh -c "(){$ functions [$ 1]} $ {@:2}"}

sdoの引数は、別のレベルのシェル解析を受けます。比較:

_$ e() echo "$@"
$ sdo e 'tname;uname'
tname
Linux
$ zsudo e 'tname;uname'
tname;uname
_
13

私にとって非常に簡単な解決策は、Sudo -sを使用してインタラクティブなシェルを呼び出すことでした。これは、私のmacOSバンドルバージョンのzsh(5.2)で機能するようです。これにより、~/.zshrcの関数が提供されます。

この動作をほのめかさないSudoマンページから:

-s、-シェル
設定されている場合は、Shell環境変数で指定されたシェル、または呼び出し元のユーザーのパスワードデータベースエントリで指定されたシェルを実行します。コマンドが指定されている場合は、シェルの-cオプションを介して実行するためにシェルに渡されます。コマンドを指定しない場合、対話型シェルが実行されます。

あなたのユースケースが何かはわかりませんが、インタラクティブなソリューションを探していると思います。

3
jhat

StéphaneChazelasの answer で説明されているソリューションの1つで、再利用可能なshorthandを作成できました。 [編集:Stéphaneは、私が提案した元のショートカットを繰り返しました。ここで説明するコードは、彼が作成した新しいバージョンです]

これを~/.zshrc

sdo() Sudo zsh -c "$functions[$1]" "$@"

これで、sdoを「ユーザー定義関数のみのSudo」として使用できます。

sdoが機能することを確認するには:ユーザー名を出力するユーザー定義関数で試してみます。

➜ birch@server ~/ ???? test() whoami

➜ birch@server ~/ ???? test
birch

➜ birch@server ~/ ???? sdo test
root
2
Birchlabs

これは私にとってはうまくいくようです:

function Sudo (){
  args="$@"
  /run/wrappers/bin/Sudo -u "$USER" zsh -i -c "$args"
}
0