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

愚かなBashのトリック:履歴、引数の再利用、ファイルとディレクトリ、関数など

システム管理者として、シェルは日常業務の一部です。シェルは、多くの場合、グラフィカルユーザーインターフェイス(GUI)よりも多くのオプションと柔軟性を提供します。毎日繰り返されるタスクは、スクリプトによって簡単に自動化できます。または、タスクを1日の特定の時間に実行するようにスケジュールすることもできます。シェルは、システムと対話するための便利な方法を提供し、より短い時間でより多くのことを実行できるようにします。 Bash、zsh、tcsh、PowerShellなど、さまざまなシェルがあります。

この2部構成のブログ投稿では、作業をスピードアップし、コーヒーを飲む時間を増やすために使用するBashワンライナーのいくつかを共有しています。この最初の投稿では、履歴、最後の引数、ファイルとディレクトリの操作、ファイルの内容の読み取り、およびBash関数について説明します。パート2では、シェル変数、findコマンド、ファイル記述子、およびリモートでの実行操作について説明します。

履歴コマンドを使用する

history コマンドは便利なものです。 History 特定のシステムで実行したコマンドや、そのコマンドに渡された引数を確認できます。 historyを使用しています 何も覚えなくてもコマンドを再実行できます。

最近のコマンドの記録は、デフォルトで~/.bash_history.に保存されます。 この場所は、HISTFILEシェル変数を変更することで変更できます。 HISTSIZE(現在のセッションのためにメモリに保存する行)やHISTFILESIZE(履歴ファイルに保持する行数)などの他の変数があります。 historyについてもっと知りたい場合 、man bashを参照してください 。

次のコマンドを実行するとします。

$> sudo systemctl status sshd

Bashはsshdサービスが実行されていないことを教えてくれるので、次にやりたいのはサービスを開始することです。以前のコマンドでステータスを確認しました。そのコマンドはhistoryに保存されました 、参照できます。実行するだけです:

$> !!:s/status/start/
sudo systemctl start sshd

上記の式の内容は次のとおりです。

  • !! -履歴の最後のコマンドを繰り返します
  • :s / status /start/-ステータスに置き換えます 開始

その結果、sshdサービスが開始されます。

次に、次のコマンドを使用して、デフォルトのHISTSIZE値を500から5000に増やします。

$> echo “HISTSIZE=5000” >> ~/.bashrc && source ~/.bashrc

履歴の最後の3つのコマンドを表示したい場合はどうすればよいですか?入力します:

$> history 3
 1002  ls
 1003  tail audit.log
 1004  history 3

tailを実行します audit.logで 履歴行番号を参照してください。この場合、1003行目を使用します:

$> !1003
tail audit.log
..
..

別の端末またはブラウザから何かをコピーし、そのコピー(コピーバッファにある)を誤って端末に貼り付けたとします。これらの行は履歴に保存されますが、これは不要なものです。ここで、HISTFILE&&の設定を解除します。 便利です

$> unset HISTFILE && exit

または

$> kill -9 $$

前のコマンドの最後の引数を参照

異なるディレクトリのディレクトリの内容を一覧表示したい場合、ディレクトリ間を頻繁に変更することがあります。前のコマンドの最後の引数を参照するために使用できる優れたトリックがあります。例:

$> pwd
/home/username/
$> ls some/very/long/path/to/some/directory
foo-file bar-file baz-file

上記の例では、/some/very/long/path/to/some/directory 前のコマンドの最後の引数です。

cdしたい場合 (ディレクトリを変更)その場所に、次のように入力します:

$> cd $_

$> pwd
/home/username/some/very/long/path/to/some/directory

次に、ダッシュ文字を使用して、元の場所に戻ります。

$> cd -
$> pwd
/home/username/

ファイルとディレクトリでの作業

ディレクトリ構造を作成し、拡張子が異なる一連のファイルをこれらのディレクトリに移動したいとします。

まず、ディレクトリを一度に作成します:

$> mkdir -v dir_{rpm,txt,zip,pdf}
mkdir: created directory 'dir_rpm'
mkdir: created directory 'dir_txt'
mkdir: created directory 'dir_zip'
mkdir: created directory 'dir_pdf'

次に、ファイル拡張子に基づいてファイルを各ディレクトリに移動します。

$> mv -- *.rpm dir_rpm/
$> mv -- *.pdf dir_pdf/
$> mv -- *.txt dir_txt/
$> mv -- *.zip dir_txt/

二点鎖線の文字-- オプションの終了を意味します。このフラグは、ダッシュで始まるファイルが引数として扱われないようにします。

次に、すべての*.txtファイルを*.logファイルに置き換え/移動したいので、次のように入力します。

$> for f in ./*.txt; do mv -v ”$file” ”${file%.*}.log”; done
renamed './file10.txt' -> './file10.log'
renamed './file1.txt' -> './file1.log'
renamed './file2.txt' -> './file2.log'
renamed './file3.txt' -> './file3.log'
renamed './file4.txt' -> './file4.log'

forを使用する代わりに 上記のループでは、prenameをインストールできます 次のようにコマンドを実行して上記の目標を達成します:

$> prename -v 's/.txt/.log/' *.txt
file10.txt -> file10.log
file1.txt -> file1.log
file2.txt -> file2.log
file3.txt -> file3.log
file4.txt -> file4.log

多くの場合、構成ファイルを変更するときは、基本的なコピーコマンドを使用して元のファイルのバックアップコピーを作成します。例:

$> cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0.back

ご覧のとおり、パス全体を繰り返してファイルに.backを追加することは、それほど効率的ではなく、おそらくエラーが発生しやすくなります。これを行うには、より短く、よりきちんとした方法があります。ここに来る:

$> cp /etc/sysconfig/network-scripts/ifcfg-eth0{,.back}

ファイルまたは変数に対してさまざまなチェックを実行できます。 help testを実行します 詳細については。

次のコマンドを使用して、ファイルがシンボリックリンクであるかどうかを確認します。

$> [[ -L /path/to/file ]] && echo “File is a symlink”

これが私が最近遭遇した問題です。一度にたくさんのファイルをgunzip/untarしたかったのです。考えずに次のように入力しました:

$> tar zxvf *.gz

結果は次のとおりです。

tar: openvpn.tar.gz: Not found in archive
tar: Exiting with failure status due to previous errors

tarファイルは次のとおりです。

iptables.tar.gz
openvpn.tar.gz
…..

なぜそれが機能しなかったのか、そしてなぜls -l *.gz 代わりに動作しますか?内部的には、次のようになります。

$> tar zxvf *.gz

次のように変換されます:

$> tar zxvf iptables.tar.gz openvpn.tar.gz
tar: openvpn.tar.gz: Not found in archive
tar: Exiting with failure status due to previous errors

tar コマンドはiptables.tar.gz内でopenvpn.tar.gzを見つけることが期待されています。単純なforでこれを解決しました ループ:

$> for f in ./*.gz; do tar zxvf "$f"; done
iptables.log
openvpn.log

Bashを使用してランダムなパスワードを生成することもできます!次に例を示します:

$> alphanum=( {a..z} {A..Z} {0..9} ); for((i=0;i<=${#alphanum[@]};i++)); do printf '%s' "${alphanum[@]:$((RANDOM%255)):1}"; done; echo

OpenSSLを使用する例を次に示します。

$> openssl rand -base64 12
JdDcLJEAkbcZfDYQ

ファイルを1行ずつ読み取る

たくさんのIPアドレスを持つファイルがあり、それらのIPアドレスを操作したいとします。たとえば、digを実行したい ファイルにリストされているIPアドレスの逆引きDNS情報を取得します。コメント(#またはハッシュタグ)で始まるIPアドレスもスキップしたい。

例としてfileAを使用します。その内容は次のとおりです。

10.10.12.13  some ip in dc1
10.10.12.14  another ip in dc2
#10.10.12.15 not used IP
10.10.12.16  another IP

各IPアドレスをコピーして貼り付けてから、digを実行できます。 手動:

$> dig +short -x 10.10.12.13

または私はこれを行うことができます:

$> while read -r ip _; do [[ $ip == \#* ]] && continue; dig +short -x "$ip"; done < ipfile

fileAの列を交換したい場合はどうなりますか?たとえば、fileAが次のようになるようにIPアドレスを右端の列に配置します。

some ip in dc1 10.10.12.13
another ip in dc2 10.10.12.14
not used IP #10.10.12.15
another IP 10.10.12.16

実行します:

$> while  read -r ip rest; do printf '%s %s\n' "$rest" "$ip"; done < fileA

Bash関数を使用する

Bashの関数は、Python、C、awk、またはその他の言語で記述されたものとは異なります。 Bashでは、1つの引数を受け入れ、「Hello world」を出力する単純な関数は、次のようになります。

func() { local arg=”$1”; echo “$arg” ; }

次のような関数を呼び出すことができます:

$> func foo

関数がそれ自体を再帰的に呼び出して、特定のタスクを実行する場合があります。例:

func() { local arg="$@"; echo "$arg"; f "$arg"; }; f foo bar

この再帰は永久に実行され、多くのリソースを利用します。 Bashでは、FUNCNESTを使用して再帰を制限できます。次の例では、再帰を5つに制限するためにFUNCNEST=5を設定しました。

func() { local arg="$@"; echo "$arg"; FUNCNEST=5; f "$arg"; }; f foo bar
foo bar
foo bar
foo bar
foo bar
foo bar
bash: f: maximum function nesting level exceeded (5)

関数を使用して、最新または最も古いファイルを取得します

特定のディレクトリにある最新のファイルを表示するためのサンプル関数は次のとおりです。

latest_file()
{
  local f latest
  for f in "${1:-.}"/*
    do
      [[ $f -nt $latest ]] && latest="$f"
    done
   printf '%s\n' "$latest"
}

この関数は、特定のディレクトリにある最も古いファイルを表示します:

oldest_file()
{
  local f oldest
  for file in "${1:-.}"/*
    do
      [[ -z $oldest || $f -ot $oldest ]] && oldest="$f"
    done
  printf '%s\n' "$oldest"
}

これらは、他の外部コマンドを呼び出さずにBashで関数を使用する方法のほんの一例です。

多くのパラメータを使用してコマンドを何度も入力していることに気付くことがあります。私がよく使用するコマンドの1つは、kubectlです。 (Kubernetes CLI)。この長いコマンドを実行するのにうんざりしています!元のコマンドは次のとおりです:

$> kubectl -n my_namespace get pods

または

$> kubectl -n my_namespace get rc,services

この構文では、-n my_namespaceを手動で含める必要があります コマンドを実行するたびに。関数を使用してこれを行う簡単な方法があります:

$> kubectl () { command kubectl -n my_namespace ”$@” ; }

これで、kubectlを実行できます -n namespaceと入力する必要はありません 毎回:

$> kubectl get pods

同じテクニックを他のコマンドにも適用できます。

まとめ

これらは、Bashに存在するいくつかの優れたトリックです。パート2では、検索やリモート実行の使用など、さらにいくつかの例を示します。コマンドライン管理タスクをより簡単かつ正確にするために、これらのトリックを練習することをお勧めします。

[無料のオンラインコース:Red HatEnterpriseLinuxの技術概要。 ]


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

  2. Linuxで最大のファイルとディレクトリを探す

  3. ubuntu /bash の下でファイルとディレクトリの名前を再帰的に変更します

  1. ディレクトリとファイルに異なる ACL を設定する

  2. bash - すべてのディレクトリ (およびコンテンツ) を削除しますが、pwd 内のファイルは削除しません

  3. お気に入りの rsync のヒントとコツ

  1. プロのようにLinuxでファイルとディレクトリを探す

  2. Bash で関数を作成して呼び出す方法

  3. Linux ファイルとディレクトリの削除