Bashスクリプト、パート4:入力と出力

Bashスクリプト:開始
Bashスクリプト、パート2:ループ
Bashスクリプト、パート3:オプションとコマンドラインスイッチ
Bashスクリプト、パート4:入力と出力
Bashスクリプト、パート5:シグナル、バックグラウンドタスク、スクリプト管理
Bashスクリプト、パート6:関数とライブラリーの開発
Bashスクリプト、パート7:sedとワープロ
Bashスクリプト、パート8:awkデータ処理言語
Bashスクリプトパート9:正規表現
Bashスクリプト、パート10:ケーススタディ
Bashスクリプト、パート11:対話型ユーティリティの期待と自動化

前回、この一連のbashスクリプト資料の第3部では、コマンドラインオプションとキーについて説明しました。 今日のトピックは、入力、出力、およびそれに関連するすべてのものです。

画像



コマンドラインスクリプトの出力を操作する2つの方法に既に慣れています。


画面に何かを表示してファイルに何かを書き込む必要がある場合があるため、Linuxでの入出力の処理方法を理解する必要があります。つまり、必要な場所にスクリプトの結果を送信する方法を学習する必要があります。 まず、標準のファイル記述子について説明します。

標準ファイル記述子


Linux上のすべてのものは、入出力を含むファイルです。 オペレーティングシステムは、記述子を使用してファイルを識別します。

各プロセスは、最大9個のファイル記述子を開くことができます。 bashシェルは、識別子0、1、および2の最初の3つの記述子を予約します。これは、それらが意味するものです。


これらの3つの特別な記述子は、スクリプト内のデータの入出力を処理します。
標準スレッドを適切に理解する必要があります。 それらは、スクリプトが外の世界と相互作用する基盤と比較することができます。 それらについての詳細を検討してください。

スタディン


STDIN —標準のシェル入力ストリームです。 端末の場合、標準入力はキーボードです。 スクリプトが入力リダイレクト文字- <使用する場合、Linuxは標準入力ファイル記述子をコマンドで指定されたものに置き換えます。 システムはファイルを読み取り、キーボードから入力されたかのようにデータを処理します。

コマンドラインでデータを取得するファイルが指定されていない場合、多くのbashコマンドはSTDINからの入力を受け入れます。 たとえば、これはcat当てはまります。

パラメーターを指定せずにコマンドラインでcatコマンドを入力すると、 STDINからの入力を受け入れSTDIN 。 次の行を入力すると、 cat単にそれを画面に表示します。

標準出力


STDOUT —標準シェル出力ストリーム。 デフォルトでは、これが画面です。 ほとんどのbashコマンドは、データをSTDOUTに出力しSTDOUT 。これにより、コンソールに表示されます。 データをそのコンテンツに添付することでファイルにリダイレクトできます。これには>>コマンドが使用されます。

したがって、このコマンドで他のデータを追加できるデータファイルがあります。

 pwd >> myfile 

どのpwdmyfileファイルに追加されますが、既にその中にあるデータはどこにも行きません。


コマンド出力をファイルにリダイレクトする

これまでのところ、すべては問題ありませんが、存在しないxfileファイルを参照して以下に示すような処理を行おうとxfileと、 myfileファイルにエラーメッセージxfileされるxfileになります。

 ls –l xfile > myfile 

このコマンドを実行すると、画面にエラーメッセージが表示されます。


存在しないファイルにアクセスしようとしています

存在しないファイルにアクセスしようとするとエラーが生成されますが、シェルはエラーメッセージをファイルにリダイレクトせず、画面に表示しました。 ただし、エラーメッセージをファイルに送信する必要がありました。 どうする 答えは簡単です-3番目の標準記述子を使用します。

ステダー


STDERRは、シェルエラーの標準ストリームです。 デフォルトでは、この記述子はSTDOUT示すものと同じことを示しているため、エラーが発生すると画面にメッセージが表示されます。

したがって、エラーメッセージを画面に表示するのではなく、たとえばログファイルなどにリダイレクトする必要があるとします。

▍エラーフローのリダイレクト


既にご存じのように、ファイル記述子STDERR — 2 STDERR — 。リダイレクトコマンドの前にこの記述子を配置することにより、エラーをリダイレクトできます。

 ls -l xfile 2>myfile cat ./myfile 

エラーメッセージはmyfileます。


エラーメッセージをファイルにリダイレクトする

errorエラーおよび出力ストリームのリダイレクト


コマンドラインスクリプトを記述するとき、エラーメッセージのリダイレクトと標準出力のリダイレクトの両方を整理する必要がある場合があります。 これを実現するために、ファイルで対応する記述子に対してリダイレクトコマンドを使用する必要があります。エラーおよび標準出力は次の場所に移動する必要があります。

 ls –l myfile xfile anotherfile 2> errorcontent 1> correctcontent 


エラーのリダイレクトと標準出力

シェルは、 1>構造のおかげで、 ls通常STDOUTに送信するものをcorrectcontentファイルにcorrectcontentます。 STDERR分類されるエラーメッセージは、リダイレクトコマンド2>ためにerrorcontentファイルに表示されます。

必要に応じて、 &>コマンドを使用して、 STDERRSTDOUT両方を同じファイルにリダイレクトできます。


STDERRとSTDOUTを同じファイルにリダイレクトする

コマンドを実行すると、 STDERRおよびSTDOUTcontentファイルに表示されます。

スクリプト出力のリダイレクト


コマンドラインスクリプトで出力をリダイレクトするには、2つの方法があります。


▍一時的な出力リダイレクト


スクリプトでは、1行の出力をSTDERRリダイレクトできます。 これを行うには、 STDERR記述子を指定してリダイレクトコマンドを使用するだけで十分ですが、記述子番号の前にアンパサンド( & )記号を配置する必要があります。

 #!/bin/bash echo "This is an error" >&2 echo "This is normal output" 

スクリプトを実行すると、デフォルトのエラーが通常のデータと同じ場所に出力されるため、両方の行が画面に表示されます。


一時的なリダイレクト

STDERRの出力がファイルにSTDERRするようにスクリプトを実行します。

 ./myscript 2> myfile 

ご覧のとおり、通常の出力がコンソールに対して行われ、エラーメッセージがファイルに表示されます。


エラーメッセージはファイルに書き込まれます。

▍永続的な出力リダイレクト


スクリプトが画面に表示される多くのデータをリダイレクトする必要がある場合、各echoコールに適切なコマンドを追加するのは不便です。 代わりに、 execコマンドを使用して、スクリプトの実行中に特定の記述子にリダイレクトされるように出力を設定できます。

 #!/bin/bash exec 1>outfile echo "This is a test of redirecting all output" echo "from a shell script to another file." echo "without having to redirect every line" 

スクリプトを実行します。


すべての出力をファイルにリダイレクトする

出力リダイレクトコマンドで指定されたファイルを見ると、 echoコマンドによって出力されたすべてのものがこのファイルに分類されていることがechoます。

execコマンドは、スクリプトの先頭だけでなく、他の場所でも使用できます。

 #!/bin/bash exec 2>myerror echo "This is the start of the script" echo "now redirecting all output to another location" exec 1>myfile echo "This should go to the myfile file" echo "and this should go to the myerror file" >&2 

これは、スクリプトを実行し、出力のリダイレクト先のファイルを表示した後に発生します。


出力を異なるファイルにリダイレクトする

execコマンドは、最初にSTDERRからの出力をmyerrorファイルにmyerrorます。 次に、いくつかのechoコマンドの出力がSTDOUT送信され、表示されます。 その後、 execコマンドがSTDOUTに入ったものをmyfileファイルに送信し、最後にechoコマンドでSTDERRへのリダイレクトコマンドを使用しますmyerror.これにより、 myerror.ファイルに対応する行がmyerror.ますmyerror.

これをマスターしたら、出力を必要な場所にリダイレクトできます。 次に、入力のリダイレクトについて説明します。

スクリプト入力のリダイレクト


入力をリダイレクトするには、出力のリダイレクトに使用したのと同じ手法を使用できます。 たとえば、 execコマンドを使用すると、 STDINデータソースをファイルにできます。

 exec 0< myfile 

このコマンドは、入力ソースが通常のSTDINではなくmyfileであることをシェルに伝えSTDIN 。 実際の入力リダイレクトを見てみましょう。

 #!/bin/bash exec 0< testfile count=1 while read line do echo "Line #$count: $line" count=$(( $count + 1 )) done 

これは、スクリプトの実行後に画面に表示されるものです。


入力リダイレクト

前の記事で、 readコマンドを使用してキーボードからユーザー入力を読み取る方法を学びました。 入力をリダイレクトしてファイルをデータソースにすると、 STDINからデータを読み取ろうとすると、キーボードからではなくファイルからreadコマンドが読み取られSTDIN

一部のLinux管理者は、このアプローチを使用してログファイルを読み取り、その後処理します。

独自の出力リダイレクトを作成する


スクリプトの入力と出力をリダイレクトすることにより、3つの標準ファイル記述子に制限されません。 既に述べたように、最大​​9つのオープン記述子を使用できます。 残りの6つは3〜8の数字で、入力または出力のリダイレクトに使用できます。 それらのいずれもファイルに割り当てて、スクリプトコードで使用できます。

execコマンドを使用して、出力にハンドルを割り当てることができます。

 #!/bin/bash exec 3>myfile echo "This should display on the screen" echo "and this should be stored in the file" >&3 echo "And this should be back on the screen" 

スクリプトの実行後、出力の一部は画面に、一部は記述子3ファイルに移動します。


ネイティブ記述子を使用した出力のリダイレクト

データ入力用のファイル記述子の作成


スクリプトは、出力と同じ方法で入力をリダイレクトできます。 データエントリをリダイレクトする前に、 STDINを別の記述子に保存しSTDIN

ファイルを読み取った後、 STDINを復元して通常どおり使用できSTDIN

 #!/bin/bash exec 6<&0 exec 0< myfile count=1 while read line do echo "Line #$count: $line" count=$(( $count + 1 )) done exec 0<&6 read -p "Are you done now? " answer case $answer in y) echo "Goodbye";; n) echo "Sorry, this is the end.";; esac 

スクリプトをテストしましょう。


入力リダイレクト

この例では、 STDINへの参照を保存するためにファイル記述子6が使用されました。 その後、入力がリダイレクトされ、ファイルがSTDINデータソースになりました。 その後、 readコマンドの入力は、リダイレクトされたSTDIN 、つまりファイルからSTDINれました。

ファイルを読み取った後、 STDINを元の状態に戻し、記述子6リダイレクトします。 ここで、すべてが正しく機能することを確認するために、スクリプトはユーザーに質問をし、キーボード入力を待機し、入力内容を処理します。

ファイル記述子を閉じる


スクリプトの終了後、シェルはファイル記述子を自動的に閉じます。 ただし、場合によっては、スクリプトの動作が完了する前に記述子を手動で閉じる必要があります。 記述子を閉じるには、 &-リダイレクトする必要があります。 次のようになります。

 #!/bin/bash exec 3> myfile echo "This is a test line of data" >&3 exec 3>&- echo "This won't work" >&3 

スクリプトの実行後、エラーメッセージが表示されます。


プライベートファイル記述子へのアクセスの試行

問題は、存在しない記述子にアクセスしようとしたことです。

スクリプトでファイル記述子を閉じるときは注意してください。 データをファイルに送信してからハンドルを閉じてから再度開くと、シェルは既存のファイルを新しいファイルに置き換えます。 つまり、以前にこのファイルに書き込まれたものはすべて失われます。

オープン記述子に関する情報の取得


Linuxで開いているすべての記述子のリストを取得するには、 lsofコマンドを使用できます。 Fedoraなどの多くのディストリビューションでは、 lsofユーティリティは/usr/sbinます。 このコマンドは、システムで開いている各記述子に関する情報を表示するため、非常に便利です。 これには、バックグラウンドで実行されているプロセスが発見したもの、およびログインしているユーザーが開いているものが含まれます。

このコマンドには多くのキーがあります。最も重要なキーを検討してください。


現在のプロセスのPIDを調べるには、シェルが現在のPID書き込む特別な環境変数$$使用できます。

-aスイッチは、他の2つのキーを使用して返された結果に対して論理演算を実行するために使用されます。

 lsof -a -p $$ -d 0,1,2 


オープン記述子情報の表示

STDINSTDOUTおよびSTDERR —関連付けられているファイルのタイプSTDERR — CHR(文字モード)です。 それらはすべて端末を指すため、ファイル名は端末に割り当てられたデバイスの名前と一致します。 3つの標準ファイルはすべて読み取りおよび書き込み可能です。

標準のスクリプトに加えて、他の記述子が開かれているスクリプトからlsofを呼び出してみましょう。

 #!/bin/bash exec 3> myfile1 exec 6> myfile2 exec 7< myfile3 lsof -a -p $$ -d 0,1,2,3,6,7 

このスクリプトを実行すると、次のようになります。


スクリプトによって開かれたファイル記述子を表示する

スクリプトは、出力用に2つの記述子( 3および6 )と入力用に1つ( 7 )を開きました。 記述子の構成に使用されるファイルへのパスもここに示されています。

出力抑制


たとえば、バックグラウンドプロセスとして実行できるスクリプトのコマンドが画面に何も表示されないようにする必要がある場合があります。 これを行うには、出力を/dev/nullリダイレクトでき/dev/null 。 それは一種のブラックホールです。

ここで、たとえば、エラーメッセージの出力を抑制する方法:

 ls -al badfile anotherfile 2> /dev/null 

たとえば、ファイルを削除せずにクリアする必要がある場合、同じアプローチが使用されます。

 cat /dev/null > myfile 

まとめ


今日は、コマンドラインスクリプトで入力と出力がどのように機能するかを学びました。 これで、ファイル記述子を処理、作成、表示、および閉じることができ、入力、出力、およびエラーストリームのリダイレクトについて理解できました。 これらはすべて、bashスクリプトの開発において非常に重要です。

次回は、Linuxシグナル、スクリプトでそれらを処理する方法、スケジュールされたタスクの実行、およびバックグラウンドタスクについて説明します。

親愛なる読者! この資料は、入力、出力、およびエラーストリームの操作の基本を提供します。 私たちはあなたの中に、経験のみによってもたらされるすべてのことを話すことができる専門家がいると確信しています。 もしそうなら-あなたに言葉を渡します。

Source: https://habr.com/ru/post/J326594/


All Articles