ln

# 通常
ln -s src link_name

# 上書き
ln -nfs src link_name

# 削除
unlink src
-s, --symbolic

ハードリンクの代わりにシンボリックリンクを作成する

-f, --force

リンクファイルと同じ名前のファイルがあっても強制的に上書きする

-n, --no-dereference

リンクの作成場所として指定したディレクトリがシンボリックリンクだった場合、参照先にリンクを作るのではなく、シンボリックリンクそのものを置き換える(-fと組み合わせて使用)

nvm

nvm

# 利用可能なすべての Node.js のバージョンをリスト表示
nvm ls

# 現在のシェルで特定バージョンの Node.js を使用する
nvm use 16

# 特定のバージョンの Node.js をインストール
nvm install 12

# 適用されている Node.js のバージョン確認は Node.js 側で確認
node -v

nodenv

# 現在のシステムにインストールされているすべての Node.js のバージョンをリストアップ
nodenv versions

# インストール可能なすべての Node.js のバージョンをリストアップ
nodenv install -l

# 指定されたバージョンの Node.js をインストール
nodenv install 15.14.0

# プロジェクトごとに異なるNode.jsのバージョンを指定する
nodenv local 15.14.0

# 適用されている Node.js のバージョン確認は Node.js 側で確認
node -v

direnv

# .envrc に環境変数を記述
echo export FOO=foo > .envrc

# .envrc にロードする env ファイルを指定
dotenv ./.env.development
# 対象のパスで direnv を有効化
direnv allow .
# 対象のパスで direnv を無効化
direnv deny .
  • .envrcexport FOO=foo といったシェル的な書き方

  • .envFOO=foo といった key-value 的な書き方

envrcenv 用の run command (略して rc)なのでスクリプト形式で書く必要がある。

touch

# タイムスタンプの更新
touch --date="2016/5/1 23:45" ファイル1 ファイル2 ...

mtr (my trace route)

mtr www.google.co.jp
options
-n

名前解決を行わない

firewall

firewall-cmd
# list
firewall-cmd --list-all
# list (full?)
firewall-cmd --list-all-zones

# add
firewall-cmd --zone=public --add-rich-rule='rule familiy=ipv4 source address="xxx.xxx.xxx.xxx/xx" port port="xxx" protocol="tcp" accept' --permanent

# remove
firewall-cmd --zone=public --remove-rich-rule='rule familiy=ipv4 source address="xxx.xxx.xxx.xxx/xx" port port="xxx" protocol="tcp" accept' --permanent

# reload
firewall-cmd --reload

grep

# コメントアウト行(#)の除外
# ref. https://qiita.com/notakaos/items/91d807f3151694e6c7a8
cat $FILE | grep -v '^\s*#' | grep -v '^\s*$'
options
-A n

対象行の後ろ n 行を出力

-B n

対象行の前 n 行を出力

-C n

対象行の前後 n 行を出力

-i

大文字小文字を無視

nginx

# conf ファイルのチェック
nginx -t

httpd

# conf ファイルのチェック
apachectl configtest

# conf ファイルのチェック(OS, ディストリビューションによってはこちら)
apache2ctl configtest

chmod

# 数値指定
chmod 755 -R ./

# シンボル指定(カンマで複数指定可能)
chmod u+rwx,g+rw,o=r -R ./
シンボルの指定について
Table 1. 対象
項目

u

ユーザー(user)、オーナー

g

グループ(group)

o

その他(others)

a

すべて(all)

設定なし

すべて(all)と同様

Table 2. 振る舞い
項目

+

指定値を追加

-

指定値を削除

=

指定値で上書き

Table 3. パーミッション
項目

r

読み込み権限

w

書き込み権限

x

実行権限

options
-R

再帰的に処理

chown

chown -R owner:group ./
options
-R

再帰的に処理

lsof

  • プロセスが開いているファイルを表示するコマンド

  • ポートを使用しているプロセスを調べられる

# port 80, 8080 を使用しているプロセスを表示
lsof -i:80,8080

groupadd, groupmod, groupdel

# グループ一覧
less /etc/group

# グループ追加
groupadd $GROUP

# グループ削除
groupdel $GROUP

useradd, usermod, userdel

# ユーザー一覧
less /etc/passwd

# ユーザー追加
useradd --create-home --shell /bin/bash --comment $COMMENT $USER

# ユーザーにグループを追加
usermod --append --groups $GROUP1,$GROUP2,$GROUP3 $USER
# ユーザーのグループを上書き(--append がない場合は上書き)
usermod --groups $GROUP1,$GROUP2,$GROUP3 $USER

# ユーザー削除
userdel --remove $USER
userdel options
--remove

ホームディレクトリを含めて削除

passwd

パスワード変更。

# 自身のパスワードを変更する
passwd

# root で他人のパスワードを変更する
passwd $USER

tee

標準出力とファイルに書き出す。

cat hoge | tee output.log

pandoc

md を pdf への変換
# `cssfile` には github のスタイルを適用するのがおすすめ
# ref. https://gist.githubusercontent.com/andyferra/2554919/raw/10ce87fe71b23216e3075d5648b8b9e56f7758e1/github.css
pandoc $srcmd -f markdown -t html5 -s -c $cssfile -o $destpdf
md を docx への変換
# ref. https://niszet.hatenablog.com/entry/2018/01/14/214800 (Markdown Preview Enhanced+pandocでdocxを出力する際のあれこれ)

# テンプレートを出力
pandoc --print-default-data-file reference.docx > reference.docx
# テンプレートを適用して md を docx に変換
pandoc $srcmd --toc --reference-doc=$templatedocx -o $destdocx

image magick

拡大縮小
convert -geometry 50% $src $dest
convert -geometry 200x200 $src $dest
# 横幅自動、縦幅固定
convert $src -resize x256 $dest
# サイズ上限を指定してリサイズ
ファイルサイズと画像サイズの指定
convert $src -resize x640 -define jpeg:extent=500kb $dest
切り抜き
# width と height は x で区切る
convert -crop $widthx$height+$x+$y $src $dest
画質
# 十の位は品質で、一の位は圧縮形式。一の位は基本 0 でよさそう
convert $src -quality 70 $dest
ファイルサイズ上限指定
convert $src -define jpeg:extent=10kb $dest
画像比較
# ref. https://gihyo.jp/admin/serial/01/ubuntu-recipe/0328?page=2
composite -compose difference imageA.png imageB.png diff.png

which

コマンドの場所を表示する。 コマンドは環境変数 PATH を元に検索される。 なお cd, echo などは内部コマンドと呼ばれており検索しても表示されない。

which man

tmux

# 起動
tmux
# 仮想ターミナルのリスト
tmux ls

# num には tmux ls での番号を指定
# 指定なしであれば最後のセッションにアタッチ
tmux attach -t $num

# num には tmux ls での番号を指定
tmux kill-session -t $num
# destroy all sessions
tmux kill-server
tmux における操作
<C-b>c

新規仮想端末作成

<C-b>d

デタッチ

<C-b><C-space>

端末切り替え

<C-b>n

次の端末

<C-b>p

前の端末

<C-b>l

最後の端末

<C-b>3

3番の端末

<C-b>w

リスト表示

<C-b>%

ペイン分割 縦

<C-b>"

ペイン分割 横

<C-b>o

ペイン切り替え

<C-b>x

破棄

<C-b>Space

よしなにペインレイアウト切り替え

<C-b>[

コピーモード。qで終了

<C-b>]

コピー内容を貼り付ける

コピーモードにおける操作
space

コピー開始位置

Enter

ハイライトされた部分をコピーし、コピーモードを終了

q

コピーモードを終了

ESC

ハイライトをキャンセル

スクリプト

起動してパネル分割してコマンド実行するスクリプトサンプル
# 上下分割して上に syslog の tail 、下に google への ping を出力
tmux new-session \; \
  split-window -v \; \
  select-pane -t 0 \; \
  send-keys 'cd /var/log' C-m \; \
  send-keys 'tail -f syslog' C-m \; \
  select-pane -t 1 \; \
  send-keys 'ping google.com' C-m \;

マウススクロール

$ cat .tmux.conf
set -g mouse on
bind -T root WheelUpPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; copy-mode -e; send-keys -M"
bind -T root WheelDownPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; send-keys -M"

このモードでコピーするときは

  • shift 押しながらマウスで範囲選択

  • ctrl+shift+c でコピー

sudo

無制限 sudo を抑止する (ec2 を例として)
# 対象ユーザーにパスワードを付与
sudo passwd ec2-user
# sudoers を変更
sudo visudo -f /etc/sudoers.d/cloud-init
# 次のように書き換え
# del: ec2-user ALL = NOPASSWD: ALL
# add: ec2-user ALL = (ALL) ALL

rsyslog

# テンプレートの宣言。(変数宣言みたいなもの)
# 先頭の $template はテンプレートディレクティブの指定。
# また先頭に $ があるものはディレクティブと考えてよい。
# XxxLogs はテンプレート名。変数名みたいなもの。後続の処理で利用する。
# "/var/log/Xxx/xxx.log" はテンプレートの中身。変数の値みたいなもの。
# なお、この書き方は古い書き方。最新では下記になる。
# template(name="XxxLogs" type=”string” string="/var/log/Xxx/xxx.log")
# type を見てわかるとおり文字列以外のテンプレートもある。
$template XxxLogs, "/var/log/Xxx/xxx.log"

# 式ベースのフィルター。
# 先頭が if だと式ベースのフィルタとなる。
# if 内の評価対象には先頭に $ を付与する。(ディレクティブなのかな。。)
# 式としては `if 評価式 then 出力先` 。
# テンプレートの値を使う場合は ? を付与する。
# 出力先に - を付与すると非同期出力。
# ref. https://blogs.itmedia.co.jp/komata/2010/03/syslog-eb63.html
# 複数のアクションを指定する場合は改行して '&' を先頭につける。
# なので下記は "ファイルに書き出し後に以降の処理は止める" という感じ。
# (別ファイルへの二重書き込みの抑止)
if $syslogfacility-text == 'daemon' and $programname contains 'xxx' then -?XxxLogs
& stop

cron

# edit
crontab -u $user -e
# list
crontab -u $user -l
# delete
crontab -u $user -r
# format
分 時 日 月 曜日 コマンド

# 毎日 00:55 に root ユーザでシャットダウンを実行
55 0 * * * root /sbin/shutdown -h +5
Table 4. 設定例
項目 設定例 コメント

リスト

0,15,30,45

分フィールドで指定した場合、15分に一度処理を実行します。

範囲

1-5

曜日フィールドで指定した場合、月曜日~金曜日に処理を実行します。

共存

1,3,7-9

時間フィールドで指定した場合、1時、3時、7時、8時、9時に処理を実行します。

間隔値

1-5/2

時間フィールドで指定した場合、1時、3時、5時に処理を実行します。なお、間隔値は、「/」の後ろに指定した値の間隔で処理を実行します。

Table 5. cron ファイルの使い分け
ファイル/ディレクトリ名 利用者 主な用途

/var/spool/cron/user

全ユーザ

ユーザの自動タスク設定ファイル

/etc/crontab

root

毎時、毎日、毎月、毎週の自動タスクのメイン設定ファイル

lsblk

ブロックデバイス情報について表示。

sudo lsblk -p
options
-p

パスを含めて表示

blkid

ブロックデバイス情報について表示。

sudo blkid

mount

# usbデバイスのマウント
sudo mount /dev/sda1 ./mnt
# isoファイルのマウント
sudo mount -o loop -t iso9660 ${src}.iso ./mnt
# アンマウント
sudo umount ./mnt

date

# 日付時刻を設定
date -s "2014/12/26 07:00:00"

# 形式指定で表示
date +"%Y%m%d%H%M%S"
options
-s

日付時刻を設定

+"format"

形式指定で表示

時刻を合わせるワンライナー
# ref. http://qiita.com/pankona/items/258fed78c168918a8ad2 (NTPを使わずに時刻を合わせるワンライナー(Proxy環境下でも安心))
date -s "$(curl -s --head http://www.google.co.jp | grep ^Date | cut -b 7-)"

tcpdump

tcpdump -ieth0 -s0 -n -X src host ${ipaddr}
options
-i

interface (対象IFは ifconfig で一覧を見れる)

-s

snaplen (データ長)

-n

Don’t convert addresses (IPアドレスやポート番号などを名前に変換せずに表示)

-X

16進で表示する際に ASCII 文字も表示

expressions
src

送信元をフィルタリングの対象とすることを指定

host

フィルタリングの対象とするホストをIPアドレスまたはホスト名を指定

du

# カレントディレクトリを対象にトップ3の使用量を表示
du -sm ./* | sort -k3 -nr

find

# 検索結果に対してgrepをかける
find . -name '*' -exec grep {} hoge \;
# 検索結果に対してgrepをかける(xargs)
find . -name '*' | xargs grep hoge

# 検索結果(カレント層、3日前まで)の log ファイルを old に移動する
find . -maxdepth 1 -name "*.log" -mtime +3 -ls -exec mv {} old/ \;
-name "PATTERN"

ファイル名

-type fD

ファイルタイプ(f はファイル、 d はディレクトリ)

-maxdepth n

検索対象を n 階層に制限する

-mtime n

データが最後に修正されたのが n 日前のファイルを検索する

find結果を加工する
find ./ -mindepth 1 -maxdepth 1 -type f | while read filename
do
  echo "$filename"
done

less

less -S ${file}
+F

モニターモード(モニターモードで Ctrl-c で通常モード、通常モードで F でモニターモード)

-S

1行表示

-s

連続した空白行を一つの空白行にまとめる

-r

画面の再描写

-N

行番号を表示

-n

行番号を計算させない

-p ${word}

wordのハイライト

terraform

# aws コマンドラインの設定
aws configure

# フォーマット
terraform fmt
# 検証
terraform validate

# 計画確認
terraform plan
# 実行
terraform apply
# 破棄
terraform destroy

# 状態ファイルの表示
terraform show
# 状態ファイルのリソースの一覧
terraform state list

# 手動で taint フラグを立てる
# taint : 汚染されている(プロビジョンで失敗した場合など)
terraform taint aws_instance.example

# tf ファイルの variable で定義した変数には default をつけるか、下記のいづれかの方法で値を設定する
# - tfvars ファイル
# - コマンドラインにて -var aaa=xxx と設定
# - 環境変数にて TF_VAR_aaa と設定
terraform apply -var 'region=us-west-2'
terraform apply -var 'amis={ us-east-1 = "foo", us-west-2 = "bar" }'
export TF_VAR_region=us-west-2

# terraform.tfvars は自動ロード
# 任意のファイルをロードする場合は -var-file で設定
terraform apply -var-file="secret.tfvars" -var-file="production.tfvars"
???
# デフォルトのリストを直接定義
variable "cidrs" { default = [] }

# タイプでリストを指定してから別で定義
variable "cidrs" { type = list }
cidrs = [ "10.0.0.0/16", "10.1.0.0/16" ]

terraform output ami

openssl

オレオレ証明書
# ref. https://dogmap.jp/2011/05/10/nginx-ssl/

# 秘密鍵生成
openssl genrsa -des3 -out server.key 2048
# 署名リクエスト生成(認証局へ提出する際に使う)
openssl req -new -key server.key -out server.csr
cp server.key server.key.org
# 秘密鍵で秘密鍵を署名
openssl rsa -in server.key.org -out server.key
# 署名リクエストと署名済み秘密鍵でサーバー証明書を生成
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

# サーバーには `server.crt` と `server.key` を格納する
# curl で叩くときは --insecure or -k が必要
secret 生成
# ランダムな 32byte を base64 で表示
openssl rand -base64 32

for

配列を処理
#!/bin/bash
for var in hoge fuga foo bar
do
    echo $var
done
10から20まで+2ずつ処理
#!/bin/bash
for var in `seq 10 2 20`
do
    echo $var
done
# 10, 12, 14, 16, 18, 20
loop でぐるぐるスクリプト
#!/bin/bash
high=(aaa bbb ccc)
middle=(iii jjj kkk)
low=(xxx yyy zzz)
for i in ${high[@]};
do
  for j in ${middle[@]};
  do
    for k in ${low[@]};
    do
      name=${i}_${j}_${k}
      echo ${name}
      mkdir ${name}
      json=$(cat << EOS
{
  "high": "${i}",
  "middle": "${j}",
  "low": "${k}"
}
EOS
)
      echo ${json} > ${name}/${name}.json
      zip -r ${name}.zip ${name}
      rm -rf ${name}
    done
  done
done
一括連番リネームワイライナー
# shell の制限あるかも(bash only かも)
i=1; for file in `ls`; do mv "$file" "$(printf "202301_%03d" "$i").${file##*.}"; i=$((i+1)); done

while

# 無限ループ
while true;do [コマンド1];[コマンド2];...;sleep [秒数];done

rsync

rsync --verbose --recursive --inplace --delete --force --compress --times --rsh='ssh -p {SSH_PORT} -i {SSH_SECRET_KEY_PATH}' {SOURCE} {DESTINATION_HOST}:{DESTINATION_PATH}
--verbose

動作内容を表示する

--recursive

ディレクトリを再帰的に処理する

--inplace

ファイルを上書きする

--delete

同期元にないファイルを同期先から削除する

--force

ディレクトリが空ではない場合も削除する

--compress

転送中のデータを圧縮する

--times

タイムスタンプを保持する

--rsh

rsh の代替を指定

スラッシュの扱いについて

# ディレクトリ A の中身を B 配下に sync する
rsync -av /SRC/A/ /DEST/B/

# ディレクトリ A 自体を B 配下に sync する
rsync -av /SRC/A /DEST/B/

tar

圧縮
# tar.gz
tar -cvzf ${DEST}.tar.gz ${SRC}
tar -cvzf ${DEST}.tgz ${SRC}
# tar.Z
tar -cvZf ${DEST}.tar.Z ${SRC}
tar -cvZf ${DEST}.taZ ${SRC}
# tar.bz2
tar -cvjf ${DEST}.tar.bz2 ${SRC}
tar -cvjf ${DEST}.tbz2 ${SRC}
# tar.xz
tar -cvJf ${DEST}.tar.xz ${SRC}
# tar
tar -cvf ${DEST}.tar ${SRC}
# zip
zip -r ${DEST}.zip ${SRC}
展開
# 自動認識
tar -xvf ${SRC}.tar.gz
# tar.gz
tar -xvzf ${SRC}.tar.gz
# tar.Z
tar -xvZf ${SRC}.tar.Z
# tar.bz2
tar -xvjf ${SRC}.tar.bz2
# tar.xz
tar -xvJf ${SRC}.tar.xz
# tar
tar -xvf ${SRC}.tar
# zip
unzip ${SRC}.zip
中身確認
tar tvzf ${SRC}.tar.gz
tar options
-c

新しいアーカイブを作成

-x

アーカイブからファイルを抽出

-v

処理されているファイルの一覧を冗長に表示

-z

gzip経由でアーカイブをフィルタ

-f

アーカイブファイルまたはデバイス

-C

ディレクトリ DIR へ移動

-t

書庫の内容を表示する

ログ圧縮

foobar.log.YYYYMMDD のようなログを圧縮する。

find ./ -name '*.log.*' -type f ! -name '*.tar.gz' -exec tar --remove-files -cvzf {}.tar.gz {} \;

ポイントは ! -name '*.tar.gz' で圧縮済みの tar.gz ファイル を除外している。

tree

tree -L 4 --charset unicode
-L

階層の指定

-d

ディレクトリオンリー

-I

対象を除外。 “xxx|yyy|zzz” で複数指定

--charset

charset の指定

dig

ドメインや ip アドレス を DNS から調べる。

dig +trace ${domain or ipaddress}

urand

ランダム文字列
# token68対応版
# fold で文字数、 head で生成数
# ref. https://qiita.com/Vit-Symty/items/5be5326c9db9de755184
cat /dev/urandom | tr -dc 'a-zA-Z0-9-._~+/' | fold -w 32 | head -n 32 | uniq
ダミーファイル生成
# 改行なしで 200MB のダミーファイル(開くとツライ)
head -c 200m /dev/urandom > test.txt
# ref. https://kazmax.zpp.jp/linux/random_file.html#ah_3

# 1行1kB(改行込み)
# head 1k で 1MB
cat /dev/urandom | tr -dc 'a-zA-Z0-9-._~+/' | fold -w 1023 | head -n 1k > dmy.txt

vagrant

# life cycle
vagrant init $name
vagrant up
vagrant ssh
vagrant halt
vagrant destroy

# box 操作
vagrant box add $title $url
vagrant box remove $title
vagrant box list

# snapshot
vagrant snapshot list
vagrant snapshot save ${snapshot_name}
vagrant snapshot restore ${snapshot_name}
vagrant snapshot delete ${snapshot_name}
Vagrantfile example
# -*- mode: ruby -*-
# vi: set ft=ruby :

# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
  # The most common configuration options are documented and commented below.
  # For a complete reference, please see the online documentation at
  # https://docs.vagrantup.com.

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://vagrantcloud.com/search.
  config.vm.box = "base"

  # ディスクサイズ
  config.disksize.size = '35GB'

  # Disable automatic box update checking. If you disable this, then
  # boxes will only be checked for updates when the user runs
  # `vagrant box outdated`. This is not recommended.
  # config.vm.box_check_update = false

  # ポートフォワード
  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # NOTE: This will enable public access to the opened port
  # config.vm.network "forwarded_port", guest: 80, host: 8080

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine and only allow access
  # via 127.0.0.1 to disable public access
  # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"

  # IP アドレスの固定
  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  config.vm.network "private_network", ip: "192.168.33.10"

  # Create a public network, which generally matched to bridged network.
  # Bridged networks make the machine appear as another physical device on
  # your network.
  # config.vm.network "public_network"

  # ホストのマウント
  # Share an additional folder to the guest VM. The first argument is
  # the path on the host to the actual folder. The second argument is
  # the path on the guest to mount the folder. And the optional third
  # argument is a set of non-required options.
  # config.vm.synced_folder "../data", "/vagrant_data"
  config.vm.synced_folder ".", "/home/vagrant/mount", :mount_options => ['dmode=775', 'fmode=664']

  # Provider-specific configuration so you can fine-tune various
  # backing providers for Vagrant. These expose provider-specific options.
  # Example for VirtualBox:
  #
  config.vm.provider "virtualbox" do |vb|
    # Display the VirtualBox GUI when booting the machine
    # vb.gui = true

    # メモリサイズ
    # Customize the amount of memory on the VM:
    vb.memory = "1024"
  end
  #
  # View the documentation for the provider you are using for more
  # information on available options.

  # プロビジョニング
  # Enable provisioning with a shell script. Additional provisioners such as
  # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
  # documentation for more information about their specific syntax and use.
  # config.vm.provision "shell", inline: <<-SHELL
  #   apt-get update
  #   apt-get install -y apache2
  # SHELL
end

dd

ディスクの完全消去
# 対象のデバイスを特定
fdisk -l
# 消去(of に対象のデバイスを指定)
dd if=/dev/zero of=/dev/sdX bs=4096 status=progress
# No space left on device(デバイス上に空きスペースがありません) で完了

# ref. https://wiki.archlinux.jp/index.php/%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF%E3%81%AE%E5%AE%8C%E5%85%A8%E6%B6%88%E5%8E%BB
ラズパイのイメージを書き込み
# ref. https://www.raspberrypi.org/documentation/installation/installing-images/linux.md

# 対象のデバイスを確認
sudo lsblk -p
# zip を展開して書き込み
unzip -p 2020-12-02-raspios-buster-armhf-lite.zip | sudo dd bs=4M of=/dev/sdb conv=fsync status=progress
ubuntu のイメージを書き込み
# 対象デバイスの確認
sudo lsblk -p
sudo fdisk -l

# 書き込み
sudo dd if=./ubuntu-ja-23.10-desktop-legacy-amd64.iso of=/dev/sda bs=4M conv=fsync status=progress

factor

素数出力
# ref. https://www.mtioutput.com/entry/factor-number-list
BEGIN=2
END=1000
seq ${BEGIN} ${END} | factor | cut -d" " -f2 | sort -nu

git

tag関係
# tag 作成
git tag v0.0.1 -m "message"
# tag 削除
git tag -d v0.0.1
# tag 一覧 (-n でメッセージの表示、数値でメッセージの行数を指定)
git tag --list
git tag --list -n3
# tag push (ブランチと一緒)
git push $remote v0.0.1
管理下にあるファイルを無視したい(update-index)
# merge, reset は処理する
git update-index --[no-]assume-unchanged $path
# merge, reset なども含む
git update-index --[no-]skip-worktree $path

# 設定確認
# assume-unchanged 対象は状態を小文字で表示
# skip-worktree 対象は状態を S と表示
git ls-files -v
リネームしても追随して差分を表示する
git diff -M
git diff --find-renames

# 類似性インデックスの閾値をパーセンテージで指定できる
git diff -M50%
古いコミットのファイルを別名でチェックアウトする
git show $COMMIT:$FILE > $NEW_FILENAME
git cat-file blob $COMMIT:$FILE > $NEW_FILENAME
git author の上書き
# 文字列で username と email を指定する
git commit --amend --author="username <user@example.com>"
差分のあるファイルを抽出してコピー
#!/bin/sh
DEST=pickup
rm -rf ${DEST}
mkdir ${DEST}
git diff --stat --name-only @^ @ | while read filepath; do
if [ -e "${filepath}" ]; then
  echo "[cp] ${filepath} to ${DEST}/fix/${filepath}"
  mkdir -p ${DEST}/org/`dirname ${filepath}`
  mkdir -p ${DEST}/fix/`dirname ${filepath}`
  cp -r "${filepath}" "${DEST}/fix/${filepath}"
else
  echo "[IGNORE] ${filepath}"
fi
done

curl

curl --show-error \
     --silent \
     --request GET \
     --insecure \
     --include \
     --header "Authorization: Bearer ${token}" \
     ${url}

# ファイルダウンロード (ex. docker-compose のダウンロード)
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
options
--insecure

SSL の警告を無視する

--include / -i

レスポンスヘッダ/ボディ表示

-d

POST のボディ部を設定

-o

ダウンロードしたファイルの格納先を指定

-L

リダイレクトがあったらリダイレクト先の情報を取る

bash の変数展開を使った例
H_CTYPE=(-H 'Content-Type:application/json; charset=UTF-8')
H_ACCEPT=(-H 'application/json')
H_AUTH=(-H 'Authorization: Bearer token')
DATA=(-d '{"foo":"1", "bar":"baz"}')
URL=http://example.com
curl -Ss -X POST -i "${H_CTYPE[@]}" "${H_ACCEPT[@]}" "${H_AUTH[@]}" "${DATA[@]}" "${URL}"

sql

sql で md5 を使ってランダムな文字列
# ref. https://lets.postgresql.jp/documents/technical/gen_data/1
SELECT md5(clock_timestamp()::text) FROM generate_series(1,3);

uuidgen

# uuid v4 を生成
uuidgen
# もしくは
cat /proc/sys/kernel/random/uuid

# 100個出力
for i in {1..100} ; do uuidgen; done

hexdump

# ファイルを1バイト単位、16進数とASCII文字でダンプする
hexdump -C ${src}

sha

ランダム文字列
date +"%s" | sha1sum | cut -b -40

md5

md5 によるファイルの差異チェック
md5sum ${file}

docker

ユーザーに docker グループを付与すると sudo が不要となる(root ユーザーレベルにもなる)。 ユーザーのグループ操作は usermod を参照。

# 起動中のコンテナ一覧を表示
docker ps
# 全コンテナ(停止中も含む)を表示
docker ps -a
# イメージの一覧を表示
docker images
# ポートのマッピングを表示
docker port $CONTAINER_NAME
# コンテナの詳細な情報を表示
docker inspect $CONTAINER_NAME

# イメージからコンテナを生成してバックグラウンドで起動。またポートを公開する
docker run -d -p $HOST_PORT:$CONTAINER_PORT --name $CONTAINER_NAME $IMAGE_TAG_NAME
# イメージからコンテナを生成して起動、およびコマンドを実行 (下記では ssh でコンテナに接続しているようなイメージ)
docker run -it $IMAGE_TAG_NAME /bin/bash
# バックグラウンドで動いているコンテナへアタッチする
docker exec -it $CONTAINER /bin/bash

# カレントディレクトリをマウントした ubuntu コンテナを起動してアタッチ
docker run -it -v `pwd`:/mnt/host:rw ubuntu /bin/bash

# コンテナ起動 (docker ps -a より確認)
docker start $CONTAINER_NAME
# コンテナ停止 (docker ps より確認)
docker stop $CONTAINER_NAME
# コンテナ削除 (docker ps -a より確認)
docker rm $CONTAINER_NAME
# イメージ削除 (docker images より確認)
docker rmi $IMAGE_TAG_NAME

# Dockerfile からイメージを生成する。 PATH に `.` を指定するとカレントディレクトリの Dockerfile を対象とする
docker build -t $IMAGE_TAG_NAME $PATH
# Docker Hub よりイメージを取得
docker pull $NAME

# 停止中のコンテナや未使用ボリュームやイメージやネットワークを全部削除する
docker system prune -f
# 個別に削除したい場合は以下のようにすればOK
docker container prune -f
docker volume prune -f
docker network prune -f
docker image prune -f

docker compose

滅びの呪文
# ref. https://qiita.com/suin/items/19d65e191b96a0079417
docker-compose down --rmi all --volumes

docker registry

image の一覧取得
# 下記とかで www-authenticate からトークン取得用のurl, service, scopeなどを確認
curl https://example.com/v2/_catalog -v

# トークン取得準備
DOCKER_REG_LOGIN_USERNAME=user
DOCKER_REG_LOGIN_PASSWORD=pass
DOCKER_AUTH_BASE_URL=https://auth.example/token

# 一覧取得
DOCKER_SERVICE=('example.com')
DOCKER_SCOPE=('registry:catalog:*')
curl -u ${DOCKER_REG_LOGIN_USERNAME}:${DOCKER_REG_LOGIN_PASSWORD} "${DOCKER_AUTH_BASE_URL}/?service=${DOCKER_SERVICE}&scope=${DOCKER_SCOPE}"

DOCKER_ACCESS_TOKEN=tokentokentoken
curl -H "Authorization: Bearer ${DOCKER_ACCESS_TOKEN}" https://example.com/v2/_catalog | jq .

# イメージのタグ一覧
DOCKER_SERVICE=('example.com')
DOCKER_SCOPE=('repository:example/image:pull')
curl -u ${DOCKER_REG_LOGIN_USERNAME}:${DOCKER_REG_LOGIN_PASSWORD} "${DOCKER_AUTH_BASE_URL}/?service=${DOCKER_SERVICE}&scope=${DOCKER_SCOPE}"

DOCKER_ACCESS_TOKEN=tokentokentoken
DOCKER_IMAGE_REPO_MNG=example/image
curl -H "Authorization: Bearer ${DOCKER_ACCESS_TOKEN}" https://example.com/v2/${DOCKER_IMAGE_REPO_MNG}/tags/list | jq .

ansible

adhoc に実行
# IP 直指定
# ref. https://dev.classmethod.jp/articles/ansible-without-inventory/
ansible -i 127.0.0.1, all -m ping (1)

# inventory から指定
ansible -i ${inventory} ${host_name} -u ${remote_user} --become -m debug -a "msg=debug!" (2)

# ansibleで収集するfacts(要素)の一覧
ansible localhost -m setup

# cronの操作(設定)
ansible -i Inventory host -m cron -a "name='jobname' minute='59' hour='18' weekday='1' job='ping'"
# cronの操作(解除)
ansible -i Inventory host -m cron -a "name='jobname' state=absent"
# cronの操作(一覧)
ansible -i Inventory host -a "crontab -l"
1 -i の値の末にカンマ(,)、またパターンとして all を付ける必要がある
2 host_name には inventory で定義されているホスト名を指定する
playbook で host 直指定
# https://tekunabe.hatenablog.jp/entry/2018/06/11/ansible_inventory_list
ansible-playbook -i 127.0.0.1, sample.yml -u ubuntu

# sample.yml
# ---
# - hosts:
#     - 127.0.0.1
#   become: yes
#   tasks:
#     - name: install
#       apt:
#         ...

秘密鍵にパスフレーズが付いていると多量の確認を行うことになる。 そのような場合には ssh-agent の章を参照。

python のバージョン競合対策

対象サーバーに自前で python をインストールしていると動かないケースがある。 そんなときは -e "ansible_python_interpreter=/usr/bin/python3" のようにオリジナルの python を指定する。

ansible-vault

# 暗号化
ansible-vault encrypt --ask-vault-pass encrypt.txt
# 復号化
ansible-vault decrypt --ask-vault-pass encrypted.txt
# 参照
ansible-vault view --ask-vault-pass encrypted.txt
# 編集
ansible-vault edit --ask-vault-pass encrypted.txt

プラクティスなディレクトリ構成

mkdir -p group_vars/
mkdir -p host_vars/
mkdir -p roles
touch production
touch staging
touch group_vars/group1.yml
touch group_vars/group2.yml
touch host_vars/hostname1.yml
touch host_vars/hostname2.yml
touch site.yml
touch webservers.yml
touch dbservers.yml

# role の生成 (roles 内で実行)
ansible-galaxy init ${role_name}

cp(copy)

# ディレクトリの中身をコピー
cp -rTv ${SRC_DIR} ${DEST_DIR}

# 再帰的にコピー
cp -r --parents ${source} ${directory}
options
-r

再帰的に処理

-T

srcの中身をdistのディレクトリに展開する

-v

コピーする内容をコンソールに表示する

-P, --parents

フォルダ構成を維持してコピー

-p, --preserve

権限などを保持してコピー

vmstat

# 1秒ごとに5回、情報を出力
DELAY=1
COUNT=5
vmstat ${DELAY} ${COUNT}
CPU ユーザーの負荷が高いケース

ユーザーが lame エンコーダーを使用して、標準のオーディオファイルを MP3 ファイルにエンコードしています。

cpu の us が 97% と高い数値を指している。

[user@RHEL ~]$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 6  1      0 302380  16356 271852    0    0   561   568   80  590 43  7 43  7  0
 1  0      0 300892  16364 273256    0    0     0    52   79  274 97  3  0  0  0
 2  0      0 299544  16364 274532    0    0     0     0   78  372 97  3  0  0  0
 1  0      0 298292  16368 275780    0    0     0     0   53  255 97  3  0  0  0
 1  0      0 296820  16368 277192    0    0     0     0   77  377 97  3  0  0  0
[user@RHEL ~]$
CPU システムの負荷が高いケース

dd を実行して、ファイルに無作為なコンテンツを追加します。 このとき、カーネルによって生成された無作為な数値を /dev/urandom が提供します。 これにより、CPU における負荷が増えます (sy – system time)。

cpu の sy が 93%-98% と高い数値を指している。

[user@RHEL ~]$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0 402944  54000 161912 745324    5   14    54    59  221  867 13  3 82  2  0
 1  0 402944  53232 161916 748396    0    0     0     0   30  213  3 97  0  0  0
 1  0 402944  49752 161920 751452    0    0     0     0   28  290  4 96  0  0  0
 1  0 402944  45804 161924 755564    0    0     0     0   29  188  2 98  0  0  0
 1  0 402944  42568 161936 758608    0    0     0 17456  272  509  7 93  0  0  0
[user@RHEL ~]$
RAM ボトルネック(スワッピング)のケース

この例では、(VirtualBox における Windows ゲストシステムなど) 多くのアプリケーションが開きます。 ほとんどすべての作業メモリーが使用されています。 次に、1 つ以上のアプリケーション (OpenOffice) が起動します。 Linux カーネルが、OpenOffice のために RAM をさらに取得するために、ハードディスクのスワップファイルに複数のメモリーページをスワップアウトします。

swap の so(スワップアウト: ディスクにスワップされているメモリー) からスワップファイルにメモリーページをスワップしていることが示されている。

[user@RHEL ~]$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 3  1 244208  10312   1552  62636    4   23    98   249   44  304 28  3 68  1  0
 0  2 244920   6852   1844  67284    0  544  5248   544  236 1655  4  6  0 90  0
 1  2 256556   7468   1892  69356    0 3404  6048  3448  290 2604  5 12  0 83  0
 0  2 263832   8416   1952  71028    0 3788  2792  3788  140 2926 12 14  0 74  0
 0  3 274492   7704   1964  73064    0 4444  2812  5840  295 4201  8 22  0 69  0
[user@RHEL ~]$
IO 読み込み負荷が高いケース

dd を使用して、/dev/null に大きなファイル (ISO ファイルなど) を読み書きします。

IO の読み込み負荷(bi 値)が高い。

[user@RHEL ~]$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 3  1 465872  36132  82588 1018364    7   17    70   127  214  838 12  3 82  3  0
 0  1 465872  33796  82620 1021820    0    0 34592     0  357  781  6 10  0 84  0
 0  1 465872  36100  82656 1019660    0    0 34340     0  358  723  5  9  0 86  0
 0  1 465872  35744  82688 1020416    0    0 33312     0  345  892  8 11  0 81  0
 0  1 465872  35716  82572 1020948    0    0 34592     0  358  738  7  8  0 85  0
[user@RHEL ~]$
IO 書き込み負荷が高いケース

dd が /dev/zero から読み込み、ファイルに書き込みます。 oflag=dsync により、データが即座にディスクに書き込まれます (そしてページキャッシュには保存されません)。

IO の書き込み負荷(bo 値)が高い。

[user@RHEL ~]$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  1      0  35628  14700 1239164    0    0  1740   652  117  601 11  4 66 20  0
 0  1      0  34852  14896 1239788    0    0     0 23096  300  573  3 16  0 81  0
 0  1      0  32780  15080 1241304    0    0     4 21000  344  526  1 13  0 86  0
 0  1      0  36512  15244 1237256    0    0     0 19952  276  394  1 12  0 87  0
 0  1      0  35688  15412 1237180    0    0     0 18904  285  465  1 13  0 86  0
[user@RHEL ~]$
CPU が IO を待っているケース

updatedb プロセスがすでに実行しています。 updatedb ユーティリティは mlocate の一部です。 これによりファイルシステム全体が調べられ locate コマンドに対してデータベースが作成されます (非常に早く実行されるファイル検索が使用されます)。 updatedb がファイルシステム全体からすべてのファイル名を読み込みますが、CPU は、IO システム (ハードディスク) からデータを取得するのを待つ必要があります。

CPU の wa(IO 待ち) の値が高い。

procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  1 403256 602848  17836 400356    5   15    50    50  207  861 13  3 83  1  0
 1  0 403256 601568  18892 400496    0    0  1048   364  337 1903  5  7  0 88  0
 0  1 403256 600816  19640 400568    0    0   748     0  259 1142  6  4  0 90  0
 0  1 403256 600300  20116 400800    0    0   476     0  196  630  8  5  0 87  0
 0  1 403256 599328  20792 400792    0    0   676     0  278 1401  7  5  0 88  0
[user@RHEL ~]$

redoc

# install
npm install -g redoc-cli

# convert
redoc-cli bundle ${SRC} -o ${DEST}

LXD

基本的な使い方
# コンテナの起動/停止/削除
IMAGE=ubuntu:18.04
lxc launch ${IMAGE} ${CONTAINER_NAME}
lxc stop ${CONTAINER_NAME}
lxc delete ${CONTAINER_NAME}

# イメージの一覧
lxc image list
# コンテナの一覧
lxc list
# コンテナの情報
lxc info ${CONTAINER_NAME}

# コンテナ内でコマンド実行 (ex. bash)
lxc exec ${CONTAINER_NAME} -- /bin/bash

# コンテナ内とのファイルコピー
lxc file pull ${CONTAINER_NAME}/${FULLPATH} ${PULLED_FILEPATH}
lxc file push ${PUSHED_FILEPATH} ${CONTAINER_NAME}/${FULLPATH}

# コンテナ名のリネーム
lxc rename ${BEF} ${AFT}

# スナップショット/リストア(info でスナップショットの一覧を確認可能)
lxc snapshot ${CONTAINER_NAME} ${SNAPSHOT_NAME}
lxc restore ${CONTAINER_NAME} ${SNAPSHOT_NAME}
# 削除時はコンテナ名/スナップショット名
lxc delte ${CONTAINER_NAME}/${SNAPSHOT_NAME}

# コンテナイメージの作成
# (alias をつけなかった場合はフィンガープリントでイメージを指定しなくてはなりません)
lxc publish ${CONTAINER_NAME} --alias ${ALIAS}
# コンテナイメージの作成(スナップショットから)
lxc publish ${CONTAINER_NAME}/${SNAPSHOT_NAME} --alias ${ALIAS}
# コンテナイメージからコンテナ起動
lxc launch ${ALIAS} ${NEW_CONTAINER_NAME}
# コンテナのアーカイブを取得(${OUTPUT}.tar.gz ができる)
lxc image export ${ALIAS} ${OUTPUT}

# ホストのディレクトリとコンテナのディレクトリをバインド
CONTAINER_NAME=foobar
DEVICE_NAME=${CONTAINER_NAME}_disk
SRC_DIR=/home/ubuntu/src
DEST_DIR=/home/ubuntu/dest
lxc config device add ${CONTAINER_NAME} ${DEVICE_NAME} disk \
  source=${SRC_DIR} \
  path=${DEST_DIR}
# ポートバインド?
lxc config device add ${CONTAINER_NAME} ${DEVICE_NAME} proxy \
  listen=tcp:0.0.0.0:80 \
  connect=tcp:127.0.0.1:8000 \
  bind=host
# デバイスを削除
lxc config device remove ${CONTAINER_NAME} ${DEVICE_NAME}
# デバイスを確認
lxc config device show ${CONTAINER_NAME}
インストールからコンフィギュレーション
# snap でインストール
sudo apt update
sudo apt install -y btrfs-progs
sudo snap install lxd --channel=3.0/stable
# ansible で configuration
sudo apt install -y software-properties-common
sudo apt-add-repository ppa:ansible/ansible
sudo apt update && sudo apt install -y ansible
ansible localhost -m group -a "name=lxd state=present" --become
sudo systemctl restart lxd
ansible localhost -m user -a "name=vagrant groups=lxd append=yes state=present" --become
# 起動
lxd init

コンテナに ssh の publickey を登録する

CONTAINER_NAME=container_name
lxc file push ~/.ssh/id_rsa.pub ${CONTAINER_NAME}/tmp/id_rsa.pub
lxc exec ${CONTAINER_NAME} -- sh -c 'cat /tmp/id_rsa.pub >> /home/ubuntu/.ssh/authorized_keys'

# コンテナのフィンガープリントを登録
ssh-keyscan -H ${CONTAINER_IP} >> ~/.ssh/known_hosts

docker を使えるように設定

lxc config set ${container} security.nesting true

VirtualBox

VirtualBox で環境作る際のノウハウ。

  • (任意) ホストネットワークマネージャからネットワークを作成

    • ip アドレスから接続する場合などは必要

    • ホストネットワークマネージャ は メニュー → ファイル の一覧の中とかにあるはず

    • dhcp は使い方がよくわからんので使わない

  • vm 作成

    • 先に設定が必要なので起動はしない

  • vm 設定

    • (任意) 対象 vm からの設定で、クリップボード共有とドラッグアンドドロップを双方向で有効化

    • (任意) 共有フォルダ設定で自動マウントをチェック

    • (任意) ネットワークのアダプター2にホストオンリーアダプターを指定

      • 名前 には最初に作成したネットワークを指定する

    • ストレージの IDE に対象の iso を指定

  • vm 起動

  • システム初期化

    • sudo apt update && sudo apt upgrade -y && sudo apt install gcc make -y

      • gcc と make はゲストエディションの実行に必要

  • (任意) ssh 設定

    • sudo apt install openssh-server -y

    • vi /etc/ssh/sshd_config

      • PasswordAuthentication を yes に変更

    • sudo systemctl enable ssh && sudo systemctl restart ssh

  • ゲストエディションの設定

    • ゲストエディションを挿入

    • ゲストエディションのマウントディレクトリから sudo sh autorun.sh

    • sudo gpasswd --add {ユーザ名} vboxsf

    • sudo reboot

  • ネットワークの設定

    • (任意) ubuntu の 設定 → ネットワーク にある Ethernet (該当 MAC アドレス)の接続設定にて ipv4 に固定 ip を指定する

      • アドレス: 192.168.xxx.101

        • 第3オクテットは最初に作成したホストネットワークマネージャのネットワークにあわせる

      • ネットマスク: 255.255.255.0

      • ゲートウェイ: 0.0.0.0

    • sudo reboot

python

poetry

# プロジェクトディレクトリを新規作成
poetry new poetry-demo
# 既存プロジェクトを初期化(カレントディレクトリが対象となる、はず)
poetry init

# 仮想環境の一覧
poetry env list
# 仮想環境の作成(python のバージョンを指定)
poetry env use python3.7
# 仮想環境の作成(python のバージョンを指定(パス指定。pyenv のパスなどを指定する))
poetry env use /full/path/to/python
# 仮想環境の削除
poetry env remove test-O3eWbxRl-py3.7

# パッケージのインストール
poetry add pendulum@^2.0.5
# --dev で開発用にインストール
poetry add --dev pytest
# git リポジトリも指定可能
poetry add git+https://github.com/sdispater/pendulum.git
# pyproject.toml をもとにパッケージをインストール
poetry install
# --no-dev で開発用パッケージを除外
poetry install --no-dev
# 依存関係のアップデート(poetry.lock を削除し再 install の実行と同じ)
poetry update
# パッケージを指定してアップデート
poetry update requests toml
# パッケージを削除(dev 用の場合は --dev を付与)
poetry remove requests

# 仮想環境でスクリプト実行(ex: pytest)
poetry run pytest
# 仮想環境をアクティベート(新規 shell 起動)
poetry shell
# 仮想環境をディアクティベート(新規 shell のまま、新規 shell を閉じるなら exit する)
poetry deactivate

# 仮想環境もろもろ情報のパス(下記はpathのみ?)
poetry env info --path

# lock ファイルの情報をエクスポート
poetry export -f requirements.txt --output requirements.txt
# poetry インストール
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 -

pipenv

pipenv は python のバージョン含めた仮想環境を構築する。(pyenv + venv)

# 仮想環境を起動(抜けるときは exit or ctrl+D)
pipenv shell
# .env を指定する場合
PIPENV_DOTENV_LOCATION=/path/to/.env pipenv shell

# 仮想環境のパス
pipenv --venv

# 仮想環境の削除
pipenv --rm

# パッケージの一覧を確認
pipenv graph

# 仮想環境の作成
pipenv --python 3.6

# パッケージのインストール
pipenv install numpy
pipenv install --dev autopep8 flake8 (1)

# pipfile からのインストール(引数なしで install)
pipenv install
pipenv install --dev (1)

# pipfile.lock からのインストール
pipenv sync
pipenv sync --dev (1)

# requirements からのインストール
pipenv install -r ./requirements.txt
# requirements 用に出力
pipenv lock -r > requirements.txt
1 --dev で開発環境向けにインストール

パッケージを消すときは下記の通り。 (Pipenv uninstallよりcleanの方が多分便利)

  • pipfileから対象を削除

  • pipenv clean

pyenv

pyenv は python のバージョンを切り替える。

# インストール可能なpythonのバージョン一覧確認
pyenv install --list

# バージョンを指定してpythonをインストール
pyenv install 3.6.7

# 特定バージョンのアンインストール
pyenv uninstall <Version>

# インストール済みのバージョン一覧の確認
pyenv versions

# pythonのバージョンをグローバルで切り替える
pyenv global 3.6.7

# 特定のディレクトリ内でのバージョンを指定する
pyenv local 3.6.7

期待する最新バージョンの python が含まれていない場合は pyenv をアップデートすると出てくるかも。

pyenv-update
# pyenv-update のインストール(インストール先はデフォルト運用の場合です)
git clone https://github.com/pyenv/pyenv-update.git /home/username/.pyenv/plugins

# アップデート
pyenv update

その他

gunicorn と uvicorn の連携
gunicorn -k uvicorn.workers.UvicornWorker app:api

duplicity (バックアップ)

# バックアップ時
duplicity --allow-source-mismatch ${src_dir} file://${dest_dir} (1) (2)
duplicity --dry-run --allow-source-mismatch ${src_dir} file://${dest_dir}
# ex)
duplicity --allow-source-mismatch /src/foo/bar file:///dest/foo/bar

# リストア時
duplicity file://${src_dir} ${dest_dir} (3)
duplicity file://${src_dir} ${dest_dir} --file-to-restore ${target}
# ex.1) `baz/foobar` がディレクトリの場合は、 `/dest/foo/bar` 直下に `baz/foobar` 直下のディレクトリやファイルを展開する
duplicity file:///src/foo/bar /dest/foo/bar --file-to-restore baz/foobar (4)
# ex.2) `baz/foobar` がファイルの場合は、 `/dest/foo/bar` としてファイルをリストアする
duplicity file:///src/foo/bar /dest/foo/bar --file-to-restore baz/foobar

# バックアップのファイル一覧出力
duplicity list-current-files <url> > list.txt (5)

# 差分チェック(ちょっと時間かかる)
duplicity verify file://${src_dir} ${target dir}
1 ${src_dir} の配下がバックアップの対象となる(${src_dir} 自体は対象外)
2 ${dest_dir} 配下にバックアップファイルが生成される(${src_dir} はコピーされない)。例えば file:///foo/bar を指定した場合、 /foo/bar 配下にバックアップファイル(xxx.gpg) が生成される
3 ${dest_dir} はディレクトリがなかった場合は生成される(ディレクトリ指定がなければ直下にリストアされる)
4 展開先と展開元のディレクトリ名やファイル名は一致させておいた方が無難(/dest/foo/bar/foobar --file-to-restore baz/foobar といった感じ)
5 標準出力に出力されるだけなので必要に応じてリダイレクト
バックアップ時
--allow-source-mismatch

ディレクトリからディレクトリなど同一ファイルシステム間でバックアップする場合は警告終了となりバックアップできない。問題ない場合はこのオプションを付与する。

--exclude

バックアップの対象外を指定する。複数指定する場合は --exclude aaa --exclude bbb といった感じで指定する。

リストア時
--file-to-restore

リストアするディレクトリ or ファイルを指定する。

mysql

# ダンプ
mysqldump -h 127.0.0.1 -u user-name -p --single-transaction --ignore-table database.table --no-tablespaces database-name > dump.sql
# リストア
mysql -h 127.0.0.1 -u user-name -p database-name < dump.sql

# 現在の接続しているスレッド数 その1
show status like 'Threads_connected';
# 現在の接続しているスレッド数 その2
SELECT * FROM information_schema.PROCESSLIST;
# プロセスリスト(処理中の接続)を表示する
show processlist;
# kill プロセス
kill プロセスNo;
共通
-p

パスワード入力を要求する

mysqldump
--single-transaction

InnoDB の場合にはアプリケーションをブロックすることなく、 START TRANSACTION が発行された時点のデータベースの一貫した状態をダンプする

--ignore-table

database.table で無視するテーブルを指定する。複数指定する場合は --ignore-table xxx --ignore-table xxx --ignore-table xxx のようにつなげる。

--no-tablespaces

???。よくわからんけど、これをつけるとあるエラーを抑止できる。

差分を見たいとき用に改行込みで整形してダンプ

mysqldump -h ${host} \
          -u ${username} \
          -p \
          --single-transaction \
          --opt \
          --skip-dump-date \
          --ignore-table ${database_table} \
          --ignore-table ${database_table} \
          --ignore-table ${database_table} \
          --no-tablespaces \
          ${databasename} \
          | sed 's$VALUES ($VALUES\n($g' | sed 's$),($),\n($g' \
          > dump.sql

ubuntu でざっくり使える状態にするスクリプト

sudo apt update && \
sudo apt upgrade -y && \
sudo apt install -y mysql-server mysql-client

sudo mysql -u root << EOS
CREATE DATABASE test_db;
SHOW DATABASES;
CREATE USER 'test_user'@'%' IDENTIFIED BY 'password';
SELECT user, host FROM mysql.user;
GRANT ALL ON test_db.* TO test_user;
SHOW GRANTS FOR 'test_user'@'%';
USE test_db;
SHOW TABLES;
EOS

# conncet: mysql -h localhost -u test_user -p test_db

psql

# 接続
psql -h ${host} -p ${port} -U ${user} -d ${database}

# バックアップ
pg_dump -h ${host} -p ${port} -U ${user} ${database_name} > backup_file_name
# リストア
psql -h $host -p $port -U $username -d $databasename -f $dumpfile
pg_dump options
--no-owner

owner を付与しない。異なる role で DB をリストアするような場合に使える。

-t

ダンプテーブルを指定。複数指定可 (ex. -t xxx -t yyy -t zzz)

pg_restore options
-t

ダンプテーブルを指定。複数指定可 (ex. -t xxx -t yyy -t zzz)

-- メタコマンド一覧
\?

-- ロール(ユーザー)一覧
\du
-- ロール(ユーザー)作成
create role rolename with login password 'password';
-- ロール(ユーザー)削除
drop role rolename;

-- データベース一覧
\l
-- データベース作成
create database newdb;
-- データベース削除
drop database targetdb;
-- データベース切り替え
\c dbname
-- 選択中のデータベースを確認
select current_database();

-- スキーマ一覧
\dn

-- テーブル一覧
\dt
-- テーブル詳細
\d tablename

-- インデックス一覧
\di
-- インデックス一覧(スキーマ指定)
\di schema.*
-- インデックス詳細
\d indexname
-- インデックス詳細(スキーマ指定)
\d schema.indexname

select 結果をファイル出力

psql ${database_name} -c '${sql};' -A -F $'\t' > output.txt
-A

桁そろえをしない

-F

タブ区切り

ssh

# 鍵の生成
ssh-keygen -t ecdsa -b 256 -C "your-email@example.com" -f id_ecdsa
ssh-keygen -t rsa -b 4096 -C "your-email@example.com" -f id_rsa

# 既存鍵の確認
ssh-keygen -l -f id_rsa.pub

# 秘密鍵から公開鍵を生成
ssh-keygen -y -f id_rsa > id_rsa.pub

# リモートサーバーに公開鍵をコピー
ssh-copy-id -i id_rsa.pub -p port your-name@address
# パスワード認証が使えない、異なるユーザーに登録する場合とか
cat ~/.ssh/id_rsa.pub | ssh username@example.com 'cat >> .ssh/authorized_keys'

# リモートホストの情報を登録
ssh-keyscan -H address >> known_hosts
ssh-keygen
-f

入出力ファイルの指定

-y

秘密鍵から公開鍵を生成。 stdout に出力されるため必要に応じてリダイレクト

-l

鍵の情報を表示

ssh-copy-id
-i

インプットとなる公開鍵の指定

ssh-keyscan
-H

リモートホストの情報をハッシュ化

pem 形式で生成
# 鍵の生成
ssh-keygen -t rsa -b 4096 -m pem -f ${output}

# 公開鍵は pem 形式で生成されないので pem 形式に変換
ssh-keygen -e -m pem -f ${input}.pub > ${output}.pub.pem
-m

形式の指定(RFC4716, PKCS98, pem)

-f

入出力のファイル指定

-e

OpenSSH 形式の秘密鍵ファイルまたは公開鍵ファイルを読み出しを指定

ssh-agent

秘密鍵のパスフレーズ入力を省略したいときに便利。 ansible とか ansible とか ansible とか。。。

# ssh-agentの起動
eval `ssh-agent`
# ssh-agentに秘密鍵を登録
ssh-add ~/.ssh/private-key

# ansible 実行
ansible --inventory staging --module-name ping servers

# ssh-agentの終了
eval `ssh-agent -k`

ssh-agent はターミナルを閉じても自動的に終了しない。 起動するごとにプロセスが溜まっていくため終了するように努める。 終了を忘れた場合には kill する。

gpg

# 鍵の生成
gpg --full-gen-key

# 登録の確認
gpg --list-keys
gpg --list-secret-keys

# 暗号化
gpg --encrypt --armor -u user-id secret.txt
# 復号化
gpg --decrypt secret.txt.asc

暗号化できるのはファイルのみの模様。ディレクトリは不可。事前に tar で圧縮するなどが必要。

鍵を使わず暗号化/復号化
# 暗号化
gpg -c --s2k-cipher-algo AES256 --s2k-digest-algo SHA512 --s2k-count 65536 doc.txt
# 復号化
gpg --output doc.txt --decrypt doc.txt.gpg
鍵のエクスポート/インポート
# 公開鍵のエクスポート
gpg --output public.key --armor --export user-id
# 公開鍵のインポート
gpg --import public.key

# 秘密鍵のエクスポート
gpg --export-secret-keys --armor user-id > secret.asc
# 秘密鍵のインポート
gpg --import secret.asc
--armor

バイナリではなく、人が見える形式(ascii)で出力

-u

対象鍵を指定。鍵の名前やメールアドレス

--export

export 対象の鍵を指定。鍵の名前やメールアドレス

apt

# パッケージインストール、更新
apt install ${package}
# パッケージ削除
apt remove ${package}
# パッケージ削除(設定ファイル含む)
apt purge ${package}
# パケージリストの更新
apt update
# インストールされているパケージの更新
apt upgrade
# インストールされているパケージの一覧
dpkg -l ${package}
# パケージリストの検索
apt-cache search ${package}
# パケージの詳細表示
apt-cache show ${package}