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


10

私には私の機能があります~/.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 '

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

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

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


また参照してください:unix.stackexchange.com/questions/181414/…(zshには独自のトリックがあるためフラグを立てない)
muru

回答:


13

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"

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

sudo zsh -c "$functions[findPort]" findPort 3306

(に渡されるインラインスクリプトは、-c ある関数の本体)。

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

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

タイピングと同じくらい短い解決策が必要sudoです。私はあなたの無名関数ソリューションをそれだけに適応させることができました。私は自分に次の関数を追加した~/.zshrc実行するための関数である、他の機能をシステム特権で:sdo() { sudo zsh -c "(){$functions[$1]} ${@:2}" }
Birchlabs

1
@Birchlabs、編集を参照
ステファンChazelas

ありがとう。提案した新しいショートカットを使用するように回答を更新しました。
Birchlabs 2016年

関数定義をsudoを介して実行されるスクリプトに追加するのは賢い方法です。ただし、その関数が別の関数(オートロードされているかどうかに関係なく)を使用する場合、十分に賢くはありません。
Damien Flament

3

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

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

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

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


これは確かに機能します。それは私が考えていたワークフローではありませんが。私の望みは、いつものユーザーとしてプロンプトにとどまり、ユーザー定義関数だけmyFuncを入力してsudo myFunc昇格させたいです。これは、プロセスなどを昇格させるのと同じ方法です(などsudo rm -rf .)。このソリューションは、私のプロンプト全体と将来のすべての機能を向上させるだけでなく、将来のすべての機能のためにユーザーを変更します—これは少しやりすぎです。
Birchlabs 2016年

このsudo -sコマンドは、スーパーユーザーとしてシェルの別のインスタンスを起動します。そのコマンドをインタラクティブに実行すると、新しいシェルはインタラクティブになります。ただし、コマンドsudo -s findPort 3306findPort 3306シェルでスーパーユーザーとしてコマンドを実行し、そのコマンドのステータスコードで終了します。
Damien Flament

2

StéphaneChazelasの回答に記載されている解決策の1つに再利用可能な省略表現を作成することができました。[編集: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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.