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)

推薦する

初心者でもjsのtypeofとinstanceofの違いを理解できます

目次1. 型2. インスタンス3. 違い1. 型typeof 演算子は、評価されていないオペランドの...

Docker データボリュームの一般的な操作コードの例

開発者が Dockerfile を使用してイメージをビルドする場合は、イメージをビルドするときにデー...

Dockerfile における ENV 命令の具体的な使用法の詳細な説明

1. Dockerfile 内の ENV 命令は、イメージの環境変数を定義するために使用されます。次...

Vueパンくずコンポーネントのカプセル化方法

Vueはパンくずコンポーネントをカプセル化して参照します。具体的な内容は次のとおりです。効果を達成す...

Linuxターミナルでの一般的なMySQL操作コマンドの詳細な説明

仕える: # chkconfig --list すべてのシステム サービスを一覧表示します # ch...

HTML Web ページ リスト タグ学習チュートリアル

HTML Web ページ リスト タグの学習チュートリアル。 HTML ページでは、リストはアウトラ...

MySQL における distinct と group by の違い

簡単に言うと、distinct は重複を削除するために使用され、group by は統計を集計するよ...

HTML/CSSにおける記号論の詳細な説明

この記事では、ソシュールの言語哲学などの理論に基づいて、CSS の class 属性は不要であると主...

MySQL の null 可能フィールドは NULL に設定する必要がありますか、それとも NOT NULL に設定する必要がありますか?

MySQL を頻繁に使用する人は、次のような状況に遭遇する可能性があります。 1. フィールド タ...

Vue プロジェクトは左スワイプ削除機能を実装します (完全なコード)

成果を達成するコードは次のとおりですhtml <テンプレート> <div> ...

Linux を使用して時間指定ファイルが占有するディスク容量を計算する方法

スケジュールされたタスク エディターを開きます。Cent は、デフォルトで vim を使用して直接開...

Google Chromeの自動入力問題に対する完璧な解決策

Google Chrome では、ログインに成功すると、パスワードを記憶するかどうかを尋ねるメッセー...

JS を使用した簡単な雪効果の例の詳細な説明

目次序文主な実装コードHTMLコードJSコード序文南の友達の多くは、雪をほとんど見たことがない、ある...

MySQL 5.6 のインストール手順(画像とテキスト付き)

MySQL はオープンソースの小規模リレーショナル データベース管理システムです。現在、MySQL...

MySQL データベースのマスター スレーブ分離のサンプル コード

導入MySQL データベースの読み取りと書き込みの分離を設定すると、データベースに対する書き込み操作...