GNU/Linux >> Linux の 問題 >  >> Linux

より愚かなBashのトリック:変数、検索、ファイル記述子、およびリモート操作

このブログ投稿は、Bashシェルを最大限に活用するための実用的なヒントとコツをカバーする2つのうちの2つ目です。パート1では、履歴、最後の引数、ファイルとディレクトリの操作、ファイルの読み取り、およびBash関数について説明しました。このセグメントでは、シェル変数、検索、ファイル記述子、およびリモート操作について説明します。

シェル変数を使用する

Bash変数は、呼び出されたときにシェルによって設定されます。 hostnameを使用する理由 $ HOSTNAMEを使用できる場合、またはwhoamiを使用する理由 $ USERを使用できるのはいつですか? Bash変数は非常に高速であり、外部アプリケーションを必要としません。

これらは、頻繁に使用されるいくつかの変数です:

$PATH
$HOME
$USER
$HOSTNAME
$PS1
..
$PS4

echoを使用する 変数を展開するコマンド。たとえば、$ PATHシェル変数は、次のコマンドを実行して展開できます。

$> echo $PATH

[今すぐダウンロード:Bashスクリプトのシステム管理者ガイド。 ]

検索コマンドを使用する

find コマンドは、おそらくLinuxオペレーティングシステム内で最も使用されているツールの1つです。インタラクティブシェルで非常に便利です。スクリプトでも使用されます。 findを使用 特定の日付より古いまたは新しいファイルを一覧表示したり、その日付に基づいてファイルを削除したり、ファイルやディレクトリのアクセス許可を変更したりできます。

このコマンドをもっとよく理解しましょう。

30日より古いファイルを一覧表示するには、次のコマンドを実行します。

$> find /tmp -type f -mtime +30

30日より古いファイルを削除するには、次のコマンドを実行します。

$> find /tmp -type f -mtime +30 -exec rm -rf {} \;

または

$> find /tmp -type f -mtime +30 -exec rm -rf {} +

上記のコマンドは、記述されているように30日より古いファイルを削除しますが、rmをフォークします。 彼らがファイルを見つけるたびにコマンド。この検索は、xargsを使用してより効率的に記述できます。 :

$> find /tmp -name '*.tmp' -exec printf '%s\0' {} \; | xargs -0 rm

findを使用できます sha256sumを一覧表示するには 実行するだけでファイル:

$> find . -type f -exec sha256sum {} +

次に、重複する.jpgファイルを検索して削除します。

$> find . -type f -name '*.jpg' -exec sha256sum {} + | sort -uk1,1 

参照ファイル記述子

Bashシェルでは、コマンドの入力と出力を管理する上でファイル記述子(FD)が重要です。多くの人がファイル記述子を正しく理解するのに問題があります。各プロセスには、次の3つのデフォルトのファイル記述子があります。

コード 意味 場所 説明
0 標準入力 / dev / stdin キーボード、ファイル、または一部のストリーム
1 標準出力 / dev / stdout モニター、端末、ディスプレイ
2 標準エラー / dev / stderr ゼロ以外の終了コードは通常>FD2、表示

デフォルトのFDが何をするかがわかったので、実際のFDを見てみましょう。 fooという名前のディレクトリを作成することから始めます 、file1が含まれています 。

$> ls foo/ bar/
ls: cannot access 'bar/': No such file or directory
foo/:
file1

出力そのようなファイルまたはディレクトリはありません 標準エラー(stderr)に移動し、画面にも表示されます。同じコマンドを実行しますが、今回は2>を使用します stderrを省略するには:

$> ls foo/ bar/ 2>/dev/null
foo/:
file1

fooの出力を送信することが可能です 標準出力(stdout)とファイルに同時に移動し、stderrを無視します。例:

$> { ls foo bar | tee -a ls_out_file ;} 2>/dev/null
foo:
file1

次に:

$> cat ls_out_file
foo:
file1

次のコマンドは、stdoutをファイルに送信し、stderrを/dev/nullに送信します。 エラーが画面に表示されないようにする:

$> ls foo/ bar/ >to_stdout 2>/dev/null
$> cat to_stdout
foo/:
file1

次のコマンドは、stdoutとstderrを同じファイルに送信します。

$> ls foo/ bar/ >mixed_output 2>&1
$> cat mixed_output
ls: cannot access 'bar/': No such file or directory
foo/:
file1

これは、stdoutとstderrが同じファイルにリダイレクトされた最後の例で起​​こったことです:

    ls foo/ bar/ >mixed_output 2>&1
             |          |
             |          Redirect stderr to where stdout is sent
             |                                                        
             stdout is sent to mixed_output

stdoutとstderrの両方を同じファイルに送信する別の短いトリック(> Bash 4.4)は、アンパサンド記号を使用します。例:

$> ls foo/ bar/ &>mixed_output

より複雑なリダイレクトは次のとおりです。

exec 3>&1 >write_to_file; echo "Hello World"; exec 1>&3 3>&-

これが発生することです:

  • exec 3>&1stdoutをファイル記述子3にコピーします
  • > write_to_fileFD1を作成してファイルに書き込みます
  • echo "Hello World" FD 1がファイルを指すようになったため、ファイルに移動します
  • exec 1>&3 FD 3を1にコピーして戻します(スワップ)
  • Three>&-ファイル記述子3を閉じます(もう必要ありません)

多くの場合、コマンドをグループ化してから、標準出力を1つのファイルに送信すると便利です。例:

$> { ls non_existing_dir; non_existing_command; echo "Hello world"; } 2> to_stderr
Hello world

ご覧のとおり、画面には「Hello world」のみが印刷されていますが、失敗したコマンドの出力はto_stderrファイルに書き込まれます。

リモート操作を実行する

Telnet、netcat、Nmap、およびその他のツールを使用して、リモートサービスが稼働しているかどうか、およびリモートサービスに接続できるかどうかをテストします。これらのツールは便利ですが、すべてのシステムにデフォルトでインストールされているわけではありません。

幸い、外部ツールを使用せずに接続をテストする簡単な方法があります。リモートサーバーがWeb、データベース、SSH、またはその他のサービスを実行しているかどうかを確認するには、次のコマンドを実行します。

$> timeout 3 bash -c ‘</dev/tcp/remote_server/remote_port’ || echo “Failed to connect”

たとえば、 serverA MariaDBサービスを実行しています:

$> timeout 3 bash -c ‘</dev/tcp/serverA/3306’ || echo “Failed to connect”

接続に失敗した場合、接続に失敗しました 画面にメッセージが表示されます。

serverAを想定します ファイアウォール/NATの背後にあります。 serverAへのデータベース接続を許可するようにファイアウォールが構成されているかどうかを確認したい 、しかし私はまだデータベースサーバーをインストールしていません。データベースポート(または他のポート)をエミュレートするには、次を使用できます:

[serverA ~]# nc -l 3306

clientA 、実行:

[clientA ~]# timeout 3 bash -c ‘</dev/tcp/serverA/3306’ || echo “Failed”

リモート接続について話している間、SSH経由でリモートサーバー上でコマンドを実行するのはどうですか?次のコマンドを使用できます:

$> ssh remotehost <<EOF  # Press the Enter key here
> ls /etc
EOF

このコマンドはls /etcを実行します リモートホスト上。

スクリプトをリモートサーバーにコピーしなくても、リモートホストでローカルスクリプトを実行することもできます。 1つの方法は次のように入力することです:

$> ssh remote_host 'bash -s' < local_script

もう1つの例は、環境変数をローカルサーバーにローカルで渡し、実行後にセッションを終了することです。

$> exec ssh remote_host ARG1=FOO ARG2=BAR 'bash -s' <<'EOF'
> printf %s\\n "$ARG1" "$ARG2"
> EOF
Password:
FOO
BAR
Connection to remote_host closed.

リモートホストで実行できる複雑なアクションは他にもたくさんあります。

まとめ

この2部構成のブログ投稿でカバーできた以上のことがBashには確かにあります。私は自分が知っていることと私が毎日扱っていることを共有しています。アイデアは、作業をエラーが発生しにくく、より楽しくすることができるいくつかのテクニックに慣れることです。

[システム管理者のスキルをテストしたいですか?今日、スキル評価を受けてください。 ]


Linux
  1. Bashのヌル区切り入力で`head`と`tail`を実行する方法は?

  2. Imgファイルのタイプを見つけてマウントする方法は?

  3. Linux.htaccessのヒントとコツ

  1. Bash を使用してファイルを検索してコピーする

  2. bashでパスと拡張子なしでファイルのベース名を抽出します

  3. パターンに一致する最新のファイルを見つけるための Bash 関数

  1. スレッドとファイル記述子

  2. Bash でファイル拡張子を再帰的に変更する

  3. x日より古いファイルまたはフォルダーを見つけて削除する