/etc/profile
スクリプトを使用してファイル内の特定の行を変更するコマンドを作成していますが、Linuxの一部のバージョンではコマンドがアクティブにならない可能性があるため、実行時にスクリプトでコマンドを使用する必要がsudo
あります。su
ファイルには/etc/profile
次の行が含まれています。
if [ "`id -u`" = "0" ]; then
echo $PATH | grep /usr/local/sbin 1> /dev/null 2> /dev/null
if [ ! $? = 0 ]; then
PATH=/usr/local/sbin:/usr/sbin:/sbin:$PATH
fi
fi
だから私はこれをしました:
$ PROFILE="/etc/profile"
$ sed '/\"`id -u`\"/ s/^if/# if/g;/\"`id -u`\"/ s/$/\nif [[ \"\$(id -u)\" == \"0\" || \"\$(id -un)\" == \"\${HOME##*\/}\" ]]; then/g;' ${PROFILE}
# if [ "`id -u`" = "0" ]; then
if [[ "$(id -u)" == "0" || "$(id -un)" == "${HOME##*/}" ]]; then
echo $PATH | grep /usr/local/sbin 1> /dev/null 2> /dev/null
if [ ! $? = 0 ]; then
PATH=/usr/local/sbin:/usr/sbin:/sbin:$PATH
fi
fi
コマンドはファイルを変更するために正しく実行されているように見えますが、su -c
次のように実行すると:
$ PROFILE="/etc/profile"
$ su -c "sed '/\"`id -u`\"/ s/^if/# if/g;/\"`id -u`\"/ s/$/\nif [[ \"\$(id -u)\" == \"0\" || \"\$(id -un)\" == \"\${HOME##*\/}\" ]]; then/g;' ${PROFILE}"
if [ "`id -u`" = "0" ]; then
echo $PATH | grep /usr/local/sbin 1> /dev/null 2> /dev/null
if [ ! $? = 0 ]; then
PATH=/usr/local/sbin:/usr/sbin:/sbin:$PATH
fi
fi
パスワードを要求して変数内のファイルを読み込みますが、行は変更しません$PROFILE
。コマンドにどのような問題がありますかsu -c
?
答え1
気づく:すべてのコードはテスト済みです。Slackware64 15.0仮想マシンで。
文字通りの答え
@ilkkachuが指摘したように、コマンドの2番目の形式で(使用数(1))二重引用符の中に一重引用符を使用します。一重引用符と二重引用符他のルールに従ってください;[1]と[2]もご覧ください。また、正規表現のみが必要です。
@waltinatorが思い出したように、重要な修正ファイルをすべてバックアップしておく必要があります。/etc/設定ファイルはい。牛に似た一種の栄養sed残念ながら、移植性のないバックアップを作成するオプションがあるため、回避策は最初に変更されたファイルのバックアップコピーを作成し、そのバックアップコピーで作業し、-i
標準出力を新しいファイルにリダイレクトすることです。
したがって、コマンドは次のようにする必要があります。
su -c 'cp /etc/profile /etc/profile.bak; sed "s,^\\(if \\[ \"\`id -u\`\".*\\)\$,\\#\\1\\
if [[ \"\$(id -u)\" == \"0\" || \"\$(id -un)\" == \"\${HOME##*/}\" ]];\
then," /etc/profile.bak > /etc/profile'
ただし、規制を遵守するにはPOSIXシェン(1p)(また:[3])次のような非POSIX構文を避けるべきです。
if [[ ... == ... || ... == ... ]]; then ...
代わりに、次のものを使用できます。
if [ ... = ... ] || [ ... = ... ]; then ...
このように:
su -c 'cp /etc/profile /etc/profile.bak; sed "s,^\\(if \\[ \"\`id -u\`\".*\\)\$,\\#\\1\\
if [ \"\$(id -u)\" = \"0\" ] || [ \"\$(id -un)\" = \"\${HOME##*/}\" ];\
then," /etc/profile.bak > /etc/profile'
実行を避けることもできます数完全に変わった/etc/設定ファイル、ファイルの場合/etc/profile.bakすでに存在しています:
if [ ! -f /etc/profile.bak ]; then
su -c 'cp /etc/profile /etc/profile.bak; sed "s,^\\(if \\[ \"\`id -u\`\".*\\)\$,\\#\\1\\
if [ \"\$(id -u)\" = \"0\" ] || [ \"\$(id -un)\" = \"\${HOME##*/}\" ];\
then," /etc/profile.bak > /etc/profile'
fi
代替(正しい)方法
コメントを見て実際にやりたいことは、利用可能なユーザーアカウントを自動的に作成することです。Sudo(8)/usr/local/sbin:/usr/sbin:/sbin
これは、重要なシステムファイルを変更するPATH
ことなく簡単に達成できます。/etc/設定ファイル。
これを行うには、次の操作を行う必要があります。
- ルートとしてログインします。ユーザーを自動的に生成するスクリプト(たとえば、
createuser
ユーザー名を最初のパラメータとして受け入れるnewuser
)を生成する場合は、次のパラメータに渡すことができます。Sudoまたは数、例えば。su -c 'createuser newuser'
。 - (ここから最後まで、おそらくスクリプトの内部になります)以下を使用して新しいユーザーアカウントを作成します。
useradd -m newuser
newuser
追加する/etc/sudoers、従って実行することができますSudoroot権限を取得します。
printf "newuser ALL=(ALL:ALL) ALL\n" >> /etc/sudoers
スクリプトではこれが少し異なります。ユーザー名を変数に保存した場合user
:
printf "%s ALL=(ALL:ALL) ALL\n" "$user" >> /etc/sudoers
/usr/local/sbin:/usr/sbin:/sbin
前にPATH
付く/home/newuser/.profile環境をカスタマイズしてください。
printf "%s\n" 'export PATH=/usr/local/sbin:/usr/sbin:/sbin${PATH+:}"$PATH"' \
>>/home/newuser/.profile
- 所有権と権限の変更/home/newuser/.profile:
chown newuser:newuser /home/newuser/.profile
chmod 644 /home/newuser/.profile
- パスワード設定
newuser
(パスワードを変更するにはttyが必要です):
passwd newuser
または、次のように設定してください。「期限切れ」、これはユーザーが次回ログインするときに強制的に設定し、ttyを必要としません。
passwd -e newuser
付録
これら2つの要件を組み合わせて設定または脱退したい場合PATH
sudoを実行して作成された環境の内部、望むよりsudo
$ PATHを保存する方法は?。 Slackware64 15.0では、基本的に上記の「解決方法」の手順に加えて追加の手順は必要ありません。
newuser@darkstar:~$ sudo sh -c 'printf "%s\n" "$PATH"'
/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/games:/usr/lib64/qt5/bin
引用する
- POSIXシェルコマンド言語、(引用符2.2、二重引用符2.2.2、二重引用符2.2.3)、
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02 - Bashマニュアル、3.1.2引用、
https://www.gnu.org/software/bash/manual/html_node/Quoting.html - POSIX シェルコマンド言語、
https://pubs.opengroup.org/onlinepubs/9699919799/idx/shell.html