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)

推薦する

VScode設定のリモートデバッグLinuxプログラムの問題を解決する

VScode リモートデバッグ Linux プログラムの問題について見てみましょう。具体的な内容は以...

ES6 ループと反復可能オブジェクトの例

この記事では、ES6 の for ... of ループについて説明します。古い方法以前は、JavaS...

JavaScript オブジェクト (詳細)

目次JavaScript オブジェクト1. 定義2. オブジェクトの分類3. オブジェクトを定義する...

MySQL 起動エラー 1067 および文字セットを変更して再起動した後の無効な回復

公式サイトからmysql-5.6.37-winx64.zipの解凍バージョンをダウンロードし、構成フ...

フロントエンド HTML+CSS+JS を使用してシンプルな TODOLIST 関数を開発する (メモ帳)

目次1. 簡単な紹介2. スクリーンショットを実行する3. コードの紹介4. まとめ1. 簡単な紹介...

Vue コンポーネントでのアンチシェイクとスロットリングの使用例の分析

入力ボックスへのユーザー入力、ウィンドウのサイズ変更、スクロール、Intersection Obse...

Linux カーネル デバイス ドライバー仮想ファイル システムに関する注意事項

/******************** * 仮想ファイルシステム VFS **********...

JS 非同期実行の原則とコールバックの詳細

1. JSの非同期実行の原則JavaScript はシングルスレッドですが、ブラウザはマルチスレッド...

一時ファイルを作成できないために MySQL が起動できない問題を解決する方法

問題の説明最近、仕事中に問題が発生しました。MySQL が起動に失敗しました。エラー ログは次のとお...

CSS のサイズと幅と高さのブラウザ解釈の違いに対する解決策

まずは例を見てみましょうコードをコピーコードは次のとおりです。 <!DOCTYPE html ...

VMware 仮想マシン ブリッジ モードでインターネットにアクセスできない問題を解決する方法

ステップ1: ローカルイーサネットプロパティをチェックして、VMwareブリッジプロトコルがインスト...

MySQL データベースの Binlog 使用法の概要 (必読)

MySQL データベースにとって binlog バイナリ ログがどれほど重要であるかについては詳し...

JavaScript 配列の詳細な概要

目次1. 配列誘導1. 文字列を配列に分割する2. コレクションとマップを新しい配列に変換する3. ...

LinuxにNginxを素早くインストールする方法

目次nginxとは1. 必要な依存関係をダウンロードする2. nginxの圧縮パッケージをダウンロー...