#
ドキュメント

Document

自分のための備忘録です。

Linux基本コマンド

cp

cp

mv

mv

find

例1

# 直下のpdfファイルを検索
$ find . -maxdepth 1 -name "*.pdf" -print

例2

$ find ~ -maxdepth 1 -name "*bash*" -print

例3 ファイルのみ検索

$ find -type f -print | xargs chmod 664

例4 grepと合わせて使用

$ find ./ -type f -print | xargs grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

例5 grepと合わせて使用(ファイルにスペースを含む対策版)

find . -maxdepth 1 -type f -print0 | xargs -0 grep -E -i -n "localhost:[0-9]{4}"

**typeオプションはグローバルオプションmaxdepthオプションの後ろに配置する必要がある。

ref. https://qiita.com/maskedw/items/2dfdf6fa7eee991ddc45

例6 最近更新されたファイルを削除

# 60分以内に更新されたファイルを削除
$ find . -type f -mmin -600 -maxdepth 1 -print | xargs rm -i

例7 ディレクトリを削除

# 60分以内に更新されたディレクトリを抽出
$ find . -type d -maxdepth 1 -mmin -600

.      <--- xargsなどに渡すときに邪魔
./www
./var
./tests
./vendor
./zap

.を除外。

$ find . -type d -maxdepth 1 -mmin -2400 -not -name "."

./www
./var
./tests
./vendor
./zap

例8 ファイルを確認して削除

$ find . -name "*.log" -exec rm -i {} \;

ref. https://techblog.kyamanak.com/entry/2018/02/12/202256

例9 ディレクトリ内のファイル数を確認

$ find . -type f | wc -l

ref. https://www-creators.com/archives/5820

例10 オーナーを指定

$ find . -type f -user ubuntu

grep

フォーマット

$ grep オプション "パターン" ファイル
# ファイルが指定されないときは標準入力
# ディレクトリをgrepする場合は`r`オプション
# カレントディレクトリをgrep
$ grep -r "パターン" ./

ref. https://www.techscore.com/blog/2012/11/28/grep%E3%81%AE%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%8A%E3%81%95%E3%82%89%E3%81%84/

# カレントディレクトリのすべてのファイルを再帰的にgrep
$ grep -r "パターン" ./
# 拡張子を`txt`に絞り込む
$ grep -r "パターン" --include="*.txt" ./
# ファイル名のみを表示する
$ grep -rl "パターン" --include="*.txt" ./

ref. https://blog.y-yuki.net/entry/2020/05/30/230000

# iオプションを抽出
$ man curl | grep -E '-i,'
# 前後3行を表示
$ grep -3 "パターン" 入力
# 前の3行を表示
$ grep -B 3 "パターン" 入力

# 後の3行を表示
$ grep -A 3 "パターン" 入力

オプション

  • E

    -E, --extended-regexp
    Interpret pattern as an extended regular expression (i.e. force grep to behave as egrep).
    ref. man grep

  • n:行番号表示
  • i:大文字小文字を区別しない

curl

Curl

zip

ディレクトリを圧縮。

$ zip -r foo.zip foo/

tar

tar

awk

Awkの正規表現はERE。

開始と終了にマッチする複数の行を取得。

$ awk '/<start pattern>/,/<end pattern>/' foo.log
# 行番号を表示
$ awk '/<start pattern>/,/<end pattern>/ {print NR, $0}' foo.log

例 auth.logからログインからログアウトを取得

$  awk '/2018-12-23T05:12:05.585870\+00:00 ip-10-0-0-200 sshd\[2772\]: pam_unix\(sshd:session\): session opened for user ubuntu by \(uid=0\)/,/2018-12-23T05:12:31.580108\+00:00 ip-10-0-0-200 sshd\[2772\]: pam_unix\(sshd:session\): session closed for user ubuntu/' auth.log

# 表示結果
2018-12-23T05:12:05.585870+00:00 ip-10-0-0-200 sshd[2772]: pam_unix(sshd:session): session opened for user ubuntu by (uid=0)
2018-12-23T05:12:05.598987+00:00 ip-10-0-0-200 systemd: pam_unix(systemd-user:session): session opened for user ubuntu by (uid=0)
2018-12-23T05:12:05.603060+00:00 ip-10-0-0-200 systemd-logind[729]: New session 70759 of user ubuntu.
2018-12-23T05:12:15.838193+00:00 ip-10-0-0-200 sudo:   ubuntu : TTY=pts/0 ; PWD=/home/ubuntu ; USER=root ; COMMAND=/usr/bin/apt update
2018-12-23T05:12:15.839194+00:00 ip-10-0-0-200 sudo: pam_unix(sudo:session): session opened for user root by ubuntu(uid=0)
2018-12-23T05:12:20.712848+00:00 ip-10-0-0-200 sudo: pam_unix(sudo:session): session closed for user root
2018-12-23T05:12:31.579074+00:00 ip-10-0-0-200 sshd[2891]: Received disconnect from 124.18.18.2 port 62931:11: disconnected by user
2018-12-23T05:12:31.579439+00:00 ip-10-0-0-200 sshd[2891]: Disconnected from user ubuntu 124.18.18.2 port 62931
2018-12-23T05:12:31.580108+00:00 ip-10-0-0-200 sshd[2772]: pam_unix(sshd:session): session closed for user ubuntu

例1) 1行目の最終列を表示

$ docker ps --all | awk 'NR==1 {print $NF}'

例2) containerをstop&rm

$ docker ps --all | awk 'NR==2 {print $1}' | xargs docker stop && xargs docker rm

例3) 2行目以降を処理

# 2行目以降を処理
$ docker image ls | awk 'NR>1 {print $3}'

例4) コンテナが1つのみ稼働しているときにexecする

$ docker exec -it $(docker ps --all | awk 'NR==2 {print $NF}') /bin/bash

例5) ドットファイルのみ出力する

$0はすべてのフィールドを表す。

$  ls -al | awk '/ \.[a-zA-Z0-9]+/ {print $0}'

\.の前の空白は重要。 パッターン/../'は、列単位ではなく行単位でマッチを試みる。 空白がないとREADME.html`など拡張子を持つファイルなどにもマッチする。

9列目のみ検索対象にする。

$ ls -al | awk '$9 ~ /\..*/ {print $9}'

9列目を2文字のみ出力

ls -al | awk '$9 = substr($9, 0, 2)  {print $9}'

ref. https://it-ojisan.tokyo/awk-substr/

jq

curl https://quartetcom.zendesk.com/api/v2/users.json \
    -u h-sawai@quartetcom.co.jp:Za0em1007K | jq "." >  users.json

整形されていないJSONファイルoriginal.jsonを整形してformatted.jsonへ出力。

$ cat original.json | jq "." > formatted.json

https://jqplay.org/

{
    "items": [{
      "foo": "aaa"  
    },
    {
      "foo": "bbb"
    }]
}
$ jq .items[ ].foo
// aaa
// bbb

ln -s

$ ln -s シンボリックリンク元 リンク先(シンボリックリンク=ショートカット)
  • シンボリックリンクをディレクトリに設定した場合、はリンク元/リンク先は同期される。
  • どちらかのディレクトリにファイルが追加されると、もう一方のディレクトリにも同期される。
  • どちらかのディレクトリのファイルを削除すると、もう一方のディレクトリからも同期される。
  • シンボリックリンクがディレクトリの場合には、シンボリックリンク(ディレクトリ)を削除した場合は、リンク元のディレクトリ(および内部のファイル)は削除されない。

重要 シンボリックリンク元、リンク配置先ともに絶対パスで指定する。相対パスだ希望どおりに動かない場合がある。 https://tweeeety.hateblo.jp/entry/20121129/1354192716

例1)

# destinationディレクトリ存在してsourceディレクトリのファイルを再帰的にdestinationにリンク
$ ln -s /path/to/source/* /path/to/destination/

例2) 例1と紛らわしい例

# destinationディレクトリ存在してもしなくてもよい
$ ln -s /path/to/source/ /path/to/destination/

# リンク先は、/path/to/destination/source になる(destinationがなければ作成される)

sed

$ sed -E -i "" s@https://example\.com@http://localhost:8888@g dump.sql

chmod

カレントディレクトリ内のディレクトリ・ファイルに再帰的に書き込み権限を付与。

$ chmod -R g+w ./*

なぜか画像ファイル(.jpg, .png)には上記では権限を付与できなかった。 以下のコマンドで付与。 以下のコマンドはディレクトリも644に変更してしまうため、ディレクトリがないことを確認後に実行。

$ chmod 664 ./*

scp

SCP(Secure Copy)は、SSHを使用してサーバからファイル(ディレクトリ)をダウンロードしたり、サーバにファイル(ディレクトリ)をアップロードする。

ダウンロード

ファイルをダウンロードする。

$ scp -P 10022 ubuntu@intra.quartetcom.co.jp:/path/to/file /path/to/local/file

フォルダをダウンロードする。
中身もダウンロードするときは、-rオプションを忘れない。

// intra.quartetcom.co.jpからフォルダごとローカルへダウンロードする例(オプション -r)を忘れない
scp -r -P 10022 ubuntu@intra.quartetcom.co.jp:/path/to/dir /path/to/local/dir

アップロード

scp -P 10022 /path/to/local/file ubuntu@intra.quartetcom.co.jp:/path/to/file

権限がないファイルをダウンロード

例として/var/log/auth.log関連をダウンロード。

$  ls -al /var/log | grep auth*

-rw-r-----  1 syslog adm    14372073 12月 14 12:05 auth.log
-rw-r-----  1 syslog adm    14302868 12月  9 06:25 auth.log.1
-rw-r-----  1 syslog adm     1232435 12月  3 06:25 auth.log.2.gz
-rw-r-----  1 syslog adm      720311 11月 25 06:25 auth.log.3.gz
-rw-r-----  1 syslog adm     1106865 11月 19 06:25 auth.log.4.gz

source_directoryへ一括コピー。

$ cd /var/log
$ sudo cp auth* source_directory

source_dirctorytarで圧縮。

$ sudo tar czf foo.tar.gz source_directory

foo.tar.gzの権限を変更。

$ sudo chown h-sawai foo.tar.gz

ローカルにダウンロード

$ scp -P 10022 h-sawai@lisket-stage:/var/log/foo.tar.gz ./foo.tar.gz

gatewayを仕様している場合

gatewayを使っているときは.ssh/configに設定したHostの値(例:lisket-web)を使う必要がある。

$ scp h-sawai@lisket-web:/home/h-sawai/whenever.bak20181015.log ./whenever.bak20181015.log

.ssh/config

Host lisket-web
Hostname 10.0.1.147
User h-sawai
StrictHostKeyChecking=no
ProxyCommand ssh -W %h:%p lisket-gateway

getwayを利用していないときは、.ssh/configのHostNameを指定すればよい。

$ mysqldump -uconststeps -p conststeps --single-transaction > /home/ubuntu/conststeps20180808.sql
$ scp -P 10022 ubuntu@intra.quartetcom.co.jp:/home/ubuntu/conststeps20180808.sql /Users/h-sawai/workspace/src/github.com/conststeps/conststeps20180808.sql

.ssh/config

Host intra
HostName        intra.quartetcom.co.jp
User            h-sawai
Port            10022

ps

ref. https://do-zan.com/mac-terminal-ps/

$ ps auxf
  • f ASCII art process hierarchy (forest).
  • a Lift the BSD-style "only yourself" restriction, which is imposed upon the set of all processes when some BSD-style (without "-") options are used or when the ps personality setting is BSD-like. The set of processes selected in this manner is in addition to the set of processes selected by other means. An alternate description is that this option causes ps to list all processes with a terminal (tty), or to list all processes when used together with the x option.
  • x Lift the BSD-style "must have a tty" restriction, which is imposed upon the set of all processes when some BSD-style (without "-") options are used or when the ps personality setting is BSD-like. The set of processes selected in this manner is in addition to the set of processes selected by other means. An alternate description is that this option causes ps to list all processes owned by you (same EUID as ps), or to list all processes when used together with the a option.
  • u Display user-oriented format.

ソート

# メモリ使用量の降順で先頭の10行表示
$ ps aux --sort -%mem | head
  • オプションにfを指定するとsortはうまく動作しない(auxfはsortではNG)。
  • -%memはメモリ使用量の降順(昇順は+%mem
  • 大文字(-%MEMはエラー)
  • 混同しやすいが、top-oオプションに項目指定とは逆なる
    • topの場合項目が大文字%MEM(小文字だとエラー)
    • なにもつけない%MEMまたは+%MEMが降順
    • -%MEMは昇順

参考リンク

top

https://milestone-of-se.nesuke.com/sv-basic/linux-basic/top-command/

# oオプションは項目指定
# メモリ使用量の降順
$ top -o %MEM
top - 04:45:16 up 7 days, 23:47,  2 users,  load average: 0.00, 0.00, 0.00
Tasks: 115 total,   1 running, 114 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.3 us,  0.0 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :    464.6 total,     23.0 free,    216.5 used,    225.1 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.    196.9 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
  80505 www-data  20   0  315812  53440  38032 S   0.0  11.2   0:00.72 apache2
MiB Mem :    464.6 total,     23.0 free,    216.5 used,    225.1 buff/cache

total、free、used、buff/cacheについてはfreeコマンドの以下の記事がわかりやすい。

ref. https://milestone-of-se.nesuke.com/sv-basic/linux-basic/free-command/

VIRT、RES、SHRについては以下の記事が分かりやすい。

https://wakatta.xyz/i41/

項目指定の注意点については、psのソートを参照。

du

以下も参照。

ディクス(ディレクトリ)の使用容量を表示する。

ref. https://www.unknownengineer.net/entry/2017/06/11/231301

基本は以下のようにして特定ディレクトリの容量を表示。

$ du -sh /path/to/directory
  • -s:総量を表示
  • -h:ヒューマンリーダブル

ワーキングディレクトリの直下のディレクトリ容量を表示。

$ du -sh */

降順でソート

$ du -sh */ | sort -nr

500MB以上のフォルダをルートから5階層走査して抽出。

$  du -g -x -m -d 5 | awk '$1 >= 500{print}'

-d 5--max-depth=5と同じ。

re. https://qiita.com/silva114jp/items/6e1e64e9aeaca62b1c04

$ cd /path/to/target
$ du -m -x -d 2 | awk '$1 >= 500{print}'

直下のディレクトリを容量でソート。

$ /var/log$ du -sh */ | sort -nr

rm

-iオプション(--interactive):ファイルの削除前に確認する

ref. https://eng-entrance.com/linux_command_rm#-i--interactive

ここではディレクトリ、特にシンボリックリンクを含むディレクトリの削除に絞って記載する。

$ ln -s /pth/to/dirA/sub /path/to/dirB/sub
dirA
    |
    |- sub 
        |
        |-- foo.txt
    
dirB
    |
    |-- text.txt
    |
    |-- sub -> dirA/sub
  • rm -r dirB/sub => シンボリックリンクの参照先(dirA/sub)は削除されない
  • rm -r dirB/sub/ => 【注意】 末尾にスラッシュありの場合はシンボリックリンクの参照先(dirA/sub)が削除される(基本的にこの形式は使用しない)
  • rm -r dirB => 内部のシンボリックリンクの参照先(dirA/sub)は削除されない。
  • rm -r dirB/ => 末尾にスラッシュありの場合に、内部のシンボリックリンクの参照先(dirA/sub)も削除されるのかを要確認(仮に参照先が削除されなくてもディレクトリの末尾にスラッシュ(/)をつけるのは非常に危険)

以上シンボリックリンクを含むディレクトリの削除は末尾にスラッシュ(/)を付与しない

# シンボリックリンクを含むディレクトリの削除は末尾にスラッシュ(`/`)を付与しない
# @see https://github.com/deployphp/deployer/blob/master/recipe/deploy/cleanup.php
OK $ rm -rf /path/to/dir
# 以下は非常にリスクが高いので使用しない
NG $ rm -rf /path/to/dir/   

ref.

rsync

eval

ls -al
drwxrwxr-x    2 ubuntu   ubuntu        4096 Apr  9 01:09 .
drwxr-xr-x   25 ubuntu   ubuntu        4096 May 21 06:52 ..
-rw-rw-r--    1 ubuntu   ubuntu         103 Apr  9 01:09 index.html
.....
.....
drwxr-xr-x    2 root     root          4096 Apr  4 16:06 sys
drwxrwxrwt    2 root     root          4096 Apr  5 04:06 tmp
drwxr-xr-x    8 root     root          4096 Apr  5 04:06 usr
drwxr-xr-x   12 root     root          4096 Apr  5 04:06 var
drwxrwxr-x    2 ubuntu   ubuntu        4096 Apr  9 01:09 web
ls -al | grep web
drwxrwxr-x    2 ubuntu   ubuntu        4096 Apr  9 01:09 web

コマンドの実行形式

  1. 変数をそのまま書く
  2. evalコマンドを使う
  3. バッククォート(`)で囲む($())と同じ

ref. https://tech-mmmm.blogspot.com/2017/11/eval.html

変数をそのまま書く

// 紛らわしいのでプロンプトを#にする
# cmd="ls -al"
# $cmd
drwxrwxr-x    2 ubuntu   ubuntu        4096 Apr  9 01:09 .
drwxr-xr-x   25 ubuntu   ubuntu        4096 May 21 06:52 ..
-rw-rw-r--    1 ubuntu   ubuntu         103 Apr  9 01:09 index.html
.....
drwxr-xr-x    2 root     root          4096 Apr  4 16:06 sys
drwxrwxrwt    2 root     root          4096 Apr  5 04:06 tmp
drwxr-xr-x    8 root     root          4096 Apr  5 04:06 usr
drwxr-xr-x   12 root     root          4096 Apr  5 04:06 var
drwxrwxr-x    2 ubuntu   ubuntu        4096 Apr  9 01:09 web
# cmd="ls -al | grep web"
$ $cmd
ls: |: No such file or directory
ls: grep: No such file or directory
web:
total 12
drwxrwxr-x    2 ubuntu   ubuntu        4096 Apr  9 01:09 .
drwxr-xr-x   25 ubuntu   ubuntu        4096 May 21 06:52 ..
-rw-rw-r--    1 ubuntu   ubuntu         103 Apr  9 01:09 index.html

上記のように変数をそのまま実行する場合は、-al | grep weblsの引数として解釈されて、目的の処理にならない。

evalコマンドを使う

# eval ls -al | grep web
drwxrwxr-x    2 ubuntu   ubuntu        4096 Apr  9 01:09 web
// or
# eval "ls -al | grep web"
drwxrwxr-x    2 ubuntu   ubuntu        4096 Apr  9 01:09 web

※1 evalコマンドの名前は、evaluate(評価する)に由来する。文字列を評価(展開)した後に実行するからだ。evalはシェルに組み込まれたビルトインコマンド。

-- https://atmarkit.itmedia.co.jp/ait/articles/1712/22/news019.html

evalは文字列ls -al | grep webをコマンドとして評価して(パイプなども適切に評価して)実行する。

バッククォート(`)で囲む($())と同じ

# `ls -al | grep web`
drwxrwxr-x: command not found

バッククォートは文字列をコマンドとして実行した結果を返す。 上記の実行された結果drwxrwxr-x 2 ubuntu ubuntu 4096 Apr 9 01:09 webがさらに実行されるが、drwxrwxr-xというコマンドはないので上記のようになる。

結果を表示したい場合は以下のようにする。

$ echo `ls -al | grep web`
drwxrwxr-x 2 ubuntu ubuntu 4096 Apr 9 01:09 web

バッククォートのユースケースは変数にコマンド実行結果を代入するときにや、コマンドの一部に実行結果を含めたいときに使用する。

aws cloudformation create-change-set \
    --stack-name base-ci \
    --template-body file://$(pwd)/cloudformation/base/ci.cf.yml --change-set-name baseciChangeSet \
    --capabilities CAPABILITY_NAMED_IAM

envsubst

以下のファイルを用意する。 名前は任意だが例としてtemplate.txtとする。

${USER}'s Home directory is ${HOME}.
${USER}'s default Shell is ${SHELL}.

envsubstコマンドはtemplate.txtの${}で囲まれな文字列を環境変数に置換して表示する。

以下$USER$HOME$SHELLは定義済みとする(通常これらの環境変数はデフォルトで定義されている)。 envsubstコマンドで環境変数に置換して標準出力に表示する。

$ envsubst < template.txt
shiroshi's Home directory is /Users/shiroshi.
shiroshi's default Shell is /usr/local/bin/zsh.

ファイルに出力する。

$ envsubst < template.txt > sample.txt
$ less sample.txt

shiroshi's Home directory is /Users/shiroshi.
shiroshi's default Shell is /usr/local/bin/zsh.

例) template.txtを以下のようにする。

Hello ${FOO}.
Hello ${BAR}.
$ export FOO=foo
$ export BAR=bar

envsubstを引数なしで実行する。 存在する環境変数をすべて代入する。

$ envsubst < template.txt
Hello foo.
Hello bar.

FOOだけに環境変数を代入する。

$ envsubst '$$FOO' < template.txt
Hello foo.
Hello ${BAR}.

FOO、BARに環境変数を代入する。

$ envsubst '$$FOO' < template.txt
Hello foo.
Hello ${BAR}.

w

ログインしているユーザー情報(USER、TTYなど)を表示する。
以下は2ユーザーがSSHログインしている。

$ w
 11:36:47 up 32 min,  2 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
ubuntu   pts/0    124.18.121.200   11:13    1:40   0.09s  0.09s -bash
ubuntu   pts/1    124.18.121.200   11:36    2.00s  0.02s  0.00s w

id

ユーザー情報を表示。

$ id
uid=501(h-sawai) gid=20(staff) groups=20(staff),701(com.apple.sharepoint.group.1),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),33(_appstore),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh),400(com.apple.access_remote_ae)

他ユーザーのSSH接続を強制的に切断

  1. wコマンドでサーバにログインしているユーザーを確認
  2. 強制的に切断したいユーザーのTTYを取得(pts/N Nは数値)
  3. ps auxf | grep pts/N(例 ubuntu 157080 0.0 1.6 17196 7760 ? S 01:31 0:00 sshd: ubuntu@pts/0
  4. kill プロセスID (上記例ではubuntu@pts/0のPIDが157080なのでkill 157080