Linux Bash スクリプトを使用してユーザーを識別する方法の例

Linux Bash スクリプトを使用してユーザーを識別する方法の例

多くの場合、bash スクリプト内またはスクリプト自体内で直接 sudo を使用してコマンドを実行する必要がありますが、これにより一連の問題が発生します。

たとえば、sudo を使用する場合、ユーザー フォルダーを参照するスクリプト内の変数 ~ または $HOME は、/home/pi などの実際のユーザー フォルダーを指す必要がありますか、それともスーパー管理者のユーザー フォルダー /root/ を指す必要がありますか?

実際には /root/ フォルダーを指していますが、これは絶対に望ましくありません。しかし、プログラムのインストールなど、多くのコマンドでは sudo を使用する必要があります。どうすればよいでしょうか?

まず、私の経験を共有させてください。コマンドライン権限の実行は、パフォーマンスの観点から次の 5 つの状況に分けられます。

  • admin-manual: 一般ユーザーが手動でコマンドを入力する
  • sudo-manual: コマンドとsudoを手動で入力します
  • admin-bash: 通常のユーザーとしてbashスクリプトを実行する
  • sudo-bash: sudo で bash スクリプトを実行する
  • root-any: rootユーザーとしてログイン

これらの 4 つの状況では、多くの変数と環境変数が混同されることがよくあります。 (混乱とはコンピュータではなく、私たち自身を指します)

また、ちょっとしたヒントがあります。

~ 変数は現在のユーザーのディレクトリを指すことは誰もが知っています。実際、~abc 形式の変数は、指定されたユーザーのユーザー ディレクトリを指すことができます。たとえば、~pi は /home/pi を指し、~ubuntu は /home/ubuntu を指します。

私たちの考えを明確にしましょう:

./test.sh など、普通にスクリプトを実行する場合は問題ありません。sudo apt-get update など、スクリプト内に sudo が登場しても問題ありません。
つまり、sudo ./test.sh! のように、スクリプト全体に対して sudo が実行された場合にのみ、深刻な問題が発生します。

実際のユーザーが pi で、HOME ディレクトリが /home/pi であるとします。ここで、sudo ./test.sh の実行モードで正しいソリューションを見つけたいと思います。
スクリプト内のさまざまなステートメントと変数、および表示される結果は次のとおりです。

# (非推奨!)
$ だれだ
>>> ルート

# whoami とは異なり、ローカルおよび ssh 経由でログインしているすべてのユーザーを含め、現在コンピューターにログインしているユーザーを表示できます。$ who am i
>>> 一部のマシンでは空と表示されます >>> Mac では次のように表示されます: pi ttys001 11 月 26 日 16:57

# whoami と同等です (非推奨!)
$ エコー $USER
>>> ルート

# ユーザーのホーム ディレクトリの場所 (信頼性が低く、推奨されません)
$HOMEをエコーする
>>> /ルート

$ ユーザーのホーム ディレクトリの場所。$HOME と同等です (推奨されません)
$ エコー ~
>>> /ルート

# 環境変数LOGNAMEを直接使用する
$ echo $LOGNAME
>>> ルート

# 環境変数LOGNAMEを明示的に呼び出す 
$ printenv ログ名
>>> ルート


# SUDO_USER は、ルートの ENV 内の環境変数です。
# 同時に、一般ユーザーには env がなく、それを表示できるのは root ユーザーだけです $ sudo echo $SUDO_USER
>>> 円周率


# 呼び出し環境変数 SUDO_USER を表示します (推奨されません)
# 結果から、スクリプトを sudo として実行した場合でも、スクリプトに sudo を追加すると異なることがわかります。
$ printenv SUDO_USER
>>> 円周率
$ sudo printenv SUDO_USER
>>> ルート

上記のテストから、sudo を使用して bash スクリプトを実行すると、多くの変数が「信頼できない」ことがわかります。

Stackoverflow では、$SUDO_USER 環境変数を使用する傾向がより一貫しています。そして、テストでは、これは確かに最も「安定」しており、つまり、さまざまな権限や OS システム (sudo のあるシステムのみ) の下で一貫性を保つことができます。

ユーザー名がわかったので、~pi のようなコマンドを使用してホーム ディレクトリ /home/pi を取得できますが、

ここで再び問題が発生します。手動で入力すると、~pi の正しいアドレスを取得できますが、スクリプトは ~pi が何であるかを認識しません。せいぜい、変数ではなく文字列です。

この場合、~abc メソッドは使用できませんが、昔ながらの、決して混乱を招かないメソッドを使用します。
/etc/passwd から直接参照してください。

手動では、passwd を直接開いて表示できますが、スクリプトでは面倒です。最も便利な方法は、システム コマンド getent (Get Entries コマンド) を使用して、指定されたユーザーの情報を取得することです。

$ getent パスワード pi
>>> pi:x:1000:1000:,,,:/home/pi:/bin/bash

したがって、残っているのは /home/pi を削除することですが、これは cut を使用して簡単に削除できます。

全体のプロセスは次のようになります。

私=$SUDO_USER
myhome=`getent passwd $me | cut -d: -f 6`

/home/pi を正常に取得しました。

さらに一歩進んで、スクリプトが sudo として実行されない場合はどうなるでしょうか?現時点では、root ユーザーおよび一般ユーザーの環境変数には SUDO_USER 変数は存在しません。次に、判断のステップを追加する必要があります。

私=${SUDO_USER:-$LOGNAME}
myhome=`getent passwd $me | cut -d: -f 6`

つまり、SUDO_USER が空の場合、通常、$LOGNAME を使用して現在のユーザーを取得します。 $USER の代わりに $LOGNAME を使用しないのはなぜですか? USER はすべてのシステムで使用できるわけではありませんが、LOGNAME はすべての *nix システムで使用できます。

更新する

一部の OS では LOGNAME を正しく取得できないため、uid メソッドを使用してユーザー パスを取得します。

HOUSE=`getent passwd ${SUDO_UID:-$(id -u)} | cut -d: -f 6`

再度更新

MacOS には /etc/passwd がなく、ユーザー情報を取得するための getent passwd <UID> メソッドをサポートしていませんが、$USER および $HOME 変数の内容は sudo では変更されません。

次のように変更します。

HOUSE=${$(`getent passwd ${SUDO_UID:-$(id -u)} | cut -d: -f 6`):-$HOME}

つまり、getent メソッドがコンテンツを取得できない場合は、$HOME の値が直接取得されます。

再度更新

bash は上記のネストされた三項式をサポートしていないため、分離する必要があります。

HOUSE="`cat /etc/passwd |grep ${SUDO_UID:-$(id -u)} | cut -d: -f 6`"
家=${家:-$ホーム}

何度も更新する

ルートの場合、grep uid は passwd に 0 が含まれるすべての行に一致するため、次のように改善する必要があります。

HOUSE="`cat /etc/passwd |grep ^${SUDO_USER:-$(id -un)}: | cut -d: -f 6`"
家=${家:-$ホーム}

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • バッチスクリプトを使用して特定のディレクトリで Git-Bash ウィンドウを起動する
  • bash のスクリプトデバッグメカニズムの詳細な説明
  • シェル スクリプト (bash スクリプト) でスペースを含む変数を処理する
  • Bashスクリプトを使用すると、シェルにログインするたびにLinuxシステム情報を表示できます。
  • Bash スクリプトを使用して Linux のメモリ使用量を監視する方法
  • bash スクリプトで ssh/scp コマンドにパスワードを渡す方法の詳細な説明
  • シェルスクリプト実行におけるsource、sh、bash、./の違いの詳細な説明
  • Linux bash スクリプト監視、WebLogic サービスの開始と停止、スクリプトの記述
  • 安全で完全に機能する Bash スクリプトの書き方

<<:  MySql 自動切り捨て例の詳細な説明

>>:  mysql5.7.19 winx64 インストールおよび構成方法のグラフィック チュートリアル (win10)

推薦する

あなたのウェブサイトはIE8に適していますか?

オリンピック期間中にIE8ベータ2がリリースされ、英語版のリリースに合わせて中国語版も第一波でリリー...

EXPLAIN を使って MySQL の SQL 実行プランを分析する方法

序文MySQL では、EXPLAIN コマンドを使用して、テーブルの接続方法や SELECT ステー...

WindowsはVMwareを使用してLinux仮想マシンを作成し、CentOS7.2オペレーティングシステムをインストールします。

目次1. ウィザードに従って仮想マシンを作成します2. オペレーティングシステムをインストールします...

CSS3のbox-shadowプロパティの使い方の詳細な例

CSS には多くの属性があります。特に複数の値を設定する必要がある属性は、長期間使用しないと忘れられ...

Vue要素と多言語切り替えの詳細な説明

目次序文複数の言語を切り替えるにはどうすればいいですか? 1. vue-i18nパッケージをインスト...

Vue3 のレンダリング関数における互換性のない変更の詳細な説明

目次レンダリングAPIの変更レンダリング関数のパラメータレンダリング関数のシグネチャの変更VNode...

Linux におけるゼロコピー技術の使用に関する簡単な分析

この記事では、Linux におけるいくつかの主要なゼロコピー テクノロジと、ゼロコピー テクノロジを...

Webページ作成の質問: 画像ファイルのパス

この記事は 123WORDPRESS.COM Lightning によるオリジナルです。転載する際に...

MySQL query_cache_type パラメータと使用方法の詳細

MySQL クエリ キャッシュを設定する目的は次のとおりです。クエリ結果をキャッシュしておくと、次回...

MySQL 5.7.18 無料インストール版ウィンドウ設定方法

初めてのブログです。データベースの勉強を始めた頃のことを書いています。自分でダウンロードしたのですが...

ウェブページでメモの詳細が灰色になる問題に対処する

1. IE では、相対的な配置、つまり <div style="background...

CSS を使用してデータ ホットスポット効果を実現する方法

効果は以下のとおりです。 分析する1. ここでは、点を囲む 3 つの円がズームアニメーションを実行し...

React仮想リストの実装

目次1. 背景2. バーチャルリストとは何か3. 関連概念の紹介4. 仮想リストの実装4.1 ドライ...

ウェブデザインにおける画像フォーマットとデザインの関係を詳しく説明

なぜこの領域のコンテンツを整理したいのでしょうか。それは、油絵の具とキャンバスを理解する必要があり、...