次のBashエイリアスを考えてみましょう。すぐに思ったけど、深く掘り下げる時間はなかった。
alias su='sudo -s'
私はBashを実行していますが、いつか共有するためにGitHubに公開できるので、このソリューションを移植可能にしたいと思います。
人々が遭遇する可能性のある問題は、すでにルートされている状態でそのプログラム(このエイリアス)を実行することです。
デモ:
$ su
[sudo] password for vlastimil:
# su
# su
#
exit
#
exit
#
exit
$
ネストされたシェルセッションを防ぐ方法はありますか?
重要:私は別のファイルではなく、ユーザーとルートに同じエイリアスファイルを使用します。ソリューションは移植可能でなければなりません(POSIX)。
答え1
su
API、セマンティクス、動作は異なるコマンドなので、sudo -s
コマンドの1つを別のコマンドにエイリアスとして指定しないでください。
ここでは、ログインシェルを起動するコマンドが必要なように見えますが、root
権限のないシェルから呼び出されたときにのみ可能なので、次のスクリプトを作成します。root
sudo
rootshell
#! /bin/sh -
die() {
printf >&2 '%s\n' "$@"
exit 1
}
[ "$#" -eq 0 ] || die "Usage: $0
Starts a root shell, no argument accepted."
[ "$(id -u)" -eq 0 ] && die "You're already superuser!"
exec sudo -s
システム構成のデフォルトのターゲットユーザーでない場合は、コマンド(またはシステムのuid 0ユーザー名)-u root
に追加します。sudo
sudo
または、スクリプトを生成したくない場合は、rootshell() (<that-code>)
コードをシェルrcファイルに追加してコードをラップしてシェル関数にします($0
すべてのシェルが関数名をに入力するわけではないため、関数名に変更$0
)。
答え2
シンプルなソリューション、シェルエイリアス
alias su='[ $(id -u) -ne 0 ] && sudo -s || echo Already root...'
POSIX互換、つまりコピーして貼り付けるか、
dash
他のシェルサポートエイリアスをほぼ推測すると、同じ動作が発生する必要があることを意味します。これが
EUID
私が直接の価値比較を完全に避ける理由です。
デモ:
$ su
[sudo] password for vlastimil:
# su
Already root...
# su
Already root...
#
exit
$
を使用することを考慮してsudo -s
添付します。sudo -s
他の変形との比較。
高度なソリューション、シェルスクリプト(POSIX)
私は上記の擬似ソリューション(別名)を長い間(数年)使用してきたので、その欠点も知っています。だから私はコードレビューにスクリプトを投稿しました。スティーブン・チャジェラス、これ質問そしてそれぞれ回答そこにあります。これから使用するスクリプトをここに配置しました。
#!/bin/sh
set -o nounset -o errexit
error()
{
printf >&2 '%s\n' "$@"
exit 1
}
is_root()
{
[ "$(id -u)" -eq 0 ]
}
start_root_shell()
{
exec sudo -s
}
if [ "$#" -gt 0 ]
then
error "Usage of $(basename "$0") script:" \
'' \
'Starts a root shell, no argument accepted.'
fi
if is_root
then
error 'You are already superuser!'
fi
start_root_shell
ありがとうスティーブン・チャジェラス私に正しい方向を教えてくれました!
答え3
この答えは、ファイルの編集に依存する2つの部分に分けられますsudoers
。 (あなたの例にはPOSIXがないか使用されていないsudo
ので、POSIX準拠に関してこの質問にどのように答えるべきかわかりませんbash
。しかし、ソリューションはこれらのツールを使用するシステム間で移植可能でなければなりません。)
ファイルにブール変数を設定すると、使い方を簡素化し、
sudo
エイリアスの使用を避けることができます。これでを使用してルートシェルにアクセスできます。shell_noargs
/etc/sudoers
sudo
sudo -s
たとえば、一部のシェルでは、
bash
変数(たとえば)を使用してシェルレベルを追跡できます$SHLVL
。これはsudo
電話をかけるか、単に入力することによって追跡できますbash
。これをシェルプロンプトに追加すると、現在持っているネストレベルを決定するのに役立ちます。
sudoers
システム提供のファイルを編集する代わりに独自のファイルを作成します。
sudo EDITOR=nano visudo -f /etc/sudoers.d/local
この行をファイルに追加して保存します。
# Allow sudo with no args to create a shell
Defaults shell_noargs
# Allow bash to share its nesting level
Defaults env_check+="SHLVL"
の場合は、(おそらくbash
または)に移動して定義された行を見つけます。を含めるように編集してください。たとえば、私のDebianシステムでは、次のように設定されています。~/.bashrc
~/.bash_profile
~/.profile
PS1
$SHLVL
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\W\$ '
次の内容を含めるように修正します$SHLVL
。
PS1='${debian_chroot:+($debian_chroot)}\u@\h[$SHLVL]:\W\$ '
最後に、ルート設定ファイルの編集を繰り返します。
使用しているシェルがbash
この機能を提供していない場合、$SHLVL
実装するのは簡単ではありません。もしシェルは起動するたびに設定ファイルを実行します。 (sh
残念ながら、POSIXはそうではありません。)