• ..

Automator

    基礎コマンド

    echo

    適当なことを表示できます。

    echo hello
    # hello
    
    # 環境変数の中を見たり
    echo $HOME
    # /Users/hoge

    less

    ファイルの中身をじっくり見る。デフォルトだと監視モード(追加データがきた時に即表示)で立ち上がります。

    less +F -N log.txt
    # 1 foo
    # 2 bar
    # 3 baz
    # :

    監視モード時にctrl+cを押すことでファイルを読むモードになります。vimのようなキーバインドが効くので、例えばggと入力するとファイルの一番から内容を見ることができます。

    • j 1行下に
    • k 1行上に

    監視モードに戻りたくなったら再度F(shift+f)を入力します。

    qで終わります。

    pwd

    現在いるディレクトリを表示

    pwd
    # /Users/hoge

    mkdir

    ディレクトリを作る。以下はfoo/ディレクトリを作りその中にさらにbar/ディレクトリを作っています。

    mkdir -p foo/bar

    cd

    ディレクトリ移動に使います。

    • ..は1つ上のディレクトリを
    • ~$HOMEディレクトリを
    • /から始めると一番トップ(ルートディレクトリ)

    をそれぞれ指します。

    pwd
    # /Users/hoge
    
    cd foo/bar
    pwd
    # /Users/hoge/foo/bar
    
    cd ../..
    pwd
    # /Users/hoge
    
    cd ~/foo
    pwd
    # /Users/hoge/foo
    
    cd /Users
    pwd
    # /Users

    ls

    現在のディレクトリにあるディレクトリやファイルを一覧する。頭がdから始まるものがディレクトリです。

    ls -al
    # total 0
    # drwxr-xr-x    4 nju33  staff   128 Feb  5 21:30 .
    # drwxr-xr-x  109 nju33  staff  3488 Feb  5 21:30 ..
    # -rw-r--r--    1 nju33  staff     0 Feb  5 21:30 index.js
    # drwxr-xr-x    2 nju33  staff    64 Feb  5 21:30 node_modules

    cp

    ファイルやディレクトリをコピーします。

    ls -al
    # total 0
    # drwxr-xr-x    2 nju33  staff    64 Feb  5 21:30 foo
    
    cp -r foo bar
    ls -al
    # total 0
    # drwxr-xr-x    2 nju33  staff    64 Feb  5 21:30 foo
    # drwxr-xr-x    2 nju33  staff    64 Feb  5 21:31 bar

    mv

    ファイルやディレクトリを移動します。

    ls -al
    # total 0
    # drwxr-xr-x    2 nju33  staff    64 Feb  5 21:30 foo
    
    mv foo bar
    ls -al
    # total 0
    # drwxr-xr-x    2 nju33  staff    64 Feb  5 21:30 bar

    rm

    ファイルやディレクトリを削除します。

    ls -al
    # drwxr-xr-x    4 nju33  staff   128 Feb  5 21:30 .
    # drwxr-xr-x  109 nju33  staff  3488 Feb  5 21:30 ..
    # -rw-r--r--    1 nju33  staff     0 Feb  5 21:30 index.js
    # drwxr-xr-x    2 nju33  staff    64 Feb  5 21:30 node_modules
    
    rm index.js
    # ディレクトリ削除には -r が必要
    rm -r node_modules
    
    ls -al
    # drwxr-xr-x    4 nju33  staff   128 Feb  5 21:30 .
    # drwxr-xr-x  109 nju33  staff  3488 Feb  5 21:30 ..

    grep

    絞り込み。

    ls -al                                                                                   
    # total 0
    # drwxr-xr-x    3 nju33  staff    96 Feb  5 21:41 .
    # drwxr-xr-x  109 nju33  staff  3488 Feb  5 21:30 ..
    # -rw-r--r--    1 nju33  staff     0 Feb  5 21:30 index.js
    
    ls -al | grep index.js
    ls -al                                                                                   
    # -rw-r--r--    1 nju33  staff     0 Feb  5 21:30 index.js

    cat

    ファイルの中身を標準出力に出す。

    cat index.js
    # function hello() {
    #   console.log(123);
    # }
    cat index.js | grep console.log
    #   console.log(123);

    zip ファイルを作る

    -rの後に生成したい zip ファイル名が来るので注意。

    zip -r name.zip ../dir-name

    zip ファイルを展開する

    指定した ZIP ファイルを展開します。-d <dest-dir>オプションを使うと展開先のディレクトリを<dest-dir>にできます。

    unzip name.zip
    unzip name.zip -d foo # foo/ に展開

    pbcopy

    使えるのは、 Mac だけです。標準入力できた内容をクリップボードにコピーします。

    echo hello | pbcopy
    # 上のあとペーストすると
    hello

    条件分岐

    基本シンタックス

    条件を[ ]で囲むか、testの後に条件を書きます。

    if [ "a" = "a" ]
      then
        echo 1
      else
        echo 2
    fi
    # 1

    改行が必要なところに;を置くことで1行で書くこともできます。

    if test "a" = "a"; then echo 1; else echo 2; fi
    # 1

    [ ! ... ]test !のように!を付けると条件の結果が反対になります。

    文字列の比較

    同じ文字列

    上記で使ったように=で文字列同士が等しいかチェックできます。左右の"a""a"は等しいので1が表示されます。

    if test "a" = "a"; then echo 1; fi
    # 1

    違う文字列

    違うかをチェックしたい場合は!=を使います。

    if test "a" != "b"; then echo 2; fi
    # 2

    空文字列

    空文字列('')かどうか調べるときは-n(non zero length)または-z(zero length)オプションを使います。

    if test -z ''; then echo 1; fi
    # 1
    
    if test ! -n ''; then echo 1; fi
    # 1
    
    if test -n 'a'; then echo 1; fi
    # 1
    
    ### 数値の比較
    
    数値の比較では`=`は使いません。代わりに以下のようなフラグを使います。
    
    - `-eq` 左と右が同じ数値か
    - `-ne` 左と右が違う数値か
    - `-lt` 左のほうが小さい
    - `-le` 左は右以下
    - `-gt` 右のほうが大きい
    - `-ge` 右は左以上
    
    ```sh
    if test 1 -eq 1; then echo 1; fi
    # 1
    
    if test 1 -ne 2; then echo 1; fi
    # 1
    
    if test 1 -lt 2; then echo 1; fi
    # 1
    
    if test 1 -le 2; then echo 1; fi
    # 1
    
    if test 2 -gt 1; then echo 1; fi
    # 1
    
    if test 2 -ge 1; then echo 1; fi
    # 1

    シェルスクリプトファイルの作り方

    1. ファイル名

    .shという拡張子を付けます。

    2. 頭にshebang(シバン)コメントを付ける

    #!で始まるコメントのことです。#!/bin/shと1行目に書きます。

    #!/bin/sh
    
    echo 1

    これをecho.shと名付けて保存したとします。

    nodejsなら#!/usr/bin/env nodeだったり色々あります。

    3. 実行権限を与える

    chmod +x echo.shを実行します。

    4. 使う

    以下のように使います。

    ./echo.sh
    # 1

    オプション付きのシェルスクリプトを書く

    Mac のgetoptsではロングオプションが使えないみたいなので、そういうの使いたい場合は他の言語つかいましょう。

    getopts

    -a-bなどハイフンで始まる cli オプションを解析してくれるコマンドです

    while getopts <条件> <変数名>; do ...; doneという書き方で書けて、すべてのオプションを繰り返し処理できます。また、このブロックの中では$OPTARGという名前でオプションの値を使うことができます。

    条件

    オプションでどの文字を使うか設定します。aと書くと-a単体で使うオプションだと設定でき、a:とコロンを置くと-a fooのようにオプション値が必要なオプションだと設定できます。

    #!/bin/sh
    
    show_list() {
      # 何か
      return 0
    }
    
    show_help() {
      echo 'command'
      echo '  何かコマンド'
      echo ''
      echo 'options'
      echo '  -l <arg>  一覧を表示'
      echo '  -h        ヘルプを表示'
      return 0
    }
    
    while getopts hl: option
    do
      case "$option" in
        "l" ) show_list $OPTARG ;;
        "h" ) show_help ;;
      esac
    done

    Linux で fish shell を使う

    以下をやります。

    1. ユーザーを作る
    2. Linuxbrew を入れる
    3. fish shell を入れる

    ちなみにマシンはAmazonLinux2です。

    ユーザーを作る

    自分(ここではnju33)ユーザーを作ります。パスワードも設定しておきます。

    sudo useradd -G wheel nju33
    sudo passwd nju33

    そして、sudoが使えるようにvisudoで以下の行のコメントを外しておきます。(#を消す)

    # %wheel        ALL=(ALL)       NOPASSWD: ALL

    Linuxbrew を入れる

    公式サイトにかかれている以下のインストールコマンドを実行します。

    sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
    # ==> This script will install:
    # /home/linuxbrew/.linuxbrew/bin/brew
    # /home/linuxbrew/.linuxbrew/share/doc/homebrew
    # ...

    おそらく/home/linuxbrewができたと思います。今のところ/home/linuxbrew/.linuxbrew/bin/brewbrewコマンドを使います。

    fish shell を入れる

    以下でfishをインストールします。

    /home/linuxbrew/.linuxbrew/bin/brew instaill fish
    # ==> Installing dependencies for hello: patchelf, zlib, binutils, linux-headers, glibc, m4, gmp, mpfr, libmpc, isl@0.18 and gcc
    # ==> Installing hello dependency: patchelf

    そしてfishを使いたいユーザーの~/.config/fish/fish.configを以下の内容にします。まず~/.config/fish/を作ります。

    mkdir -p ~/.config/fish

    そしてviなどで以下のようにファイルを作ります。これでbrewとそれを使ってインストールしたものへのパスが通り使えるようになります。

    set -x HOMEBREW_PREFIX /home/linuxbrew/.linuxbrew
    set -x HOMEBREW_CELLAR /home/linuxbrew/.linuxbrew/Cellar
    set -x HOMEBREW_REPOSITORY /home/linuxbrew/.linuxbrew/Homebrew
    set -x PATH /home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin $PATH
    set -x MANPATH /home/linuxbrew/.linuxbrew/share/man $MANPATH
    set -x INFOPATH /home/linuxbrew/.linuxbrew/share/info $INFOPATH

    デフォルトシェルを fish shell にする

    そのユーザーでログインした時にfishで始められるようにします。それにはまず、/etc/shellsfishbinまでのパスを追加してあげます。

    sudo viなどで/etc/shellsを開いて、以下の一行を追加します。

    /home/linuxbrew/.linuxbrew/bin/fish

    chsh -lで上の一行が増えていれば大丈夫です。

    chsh -s [chsh -l 結果のどれか]でそのユーザーのデフォルトシェルを切り替えられます。ではfishに変えます。

    chsh -s /home/linuxbrew/.linuxbrew/bin/fish
    # Changing shell for nju33.
    # Password: 
    # Shell changed.

    ここまで終わったらログインし直します。

    おまけ oh-my-fish を入れる

    ログインし直すと、brewfishなどが使えるようになっていると思います。(もし、使えない場合は.config/fish/config.fishを確認してください)

    fishが使えるのでoh-my-fish推奨の以下でただ入れることができます。

    curl -L https://get.oh-my.fish | fish

    僕が好きなedenテーマも入れます。

    omf install eden
    # Updating https://github.com/oh-my-fish/packages-main master... Done!
    # Installing package eden
    # ✔ eden successfully installed.

    デフォルトシェルを変更する

    shellbin自体は何らかの方法で取得済みという状態だとします。ここの例ではfishをデフォルトシェルに変更してみます。

    /etc/shellsへ追記

    そのbinへのパスを/etc/shellsへ追記します。
    ここではそのパスは/home/linuxbrew/.linuxbrew/bin/fishになるのでこれを追記します。

    sudo vi /etc/shells
    # /home/linuxbrew/.linuxbrew/bin/fish と追記

    追記内容の確認

    以下で確認できます。

    chsh -l
    # /bin/sh
    # /bin/bash
    # /sbin/nologin
    # /bin/dash
    # /home/linuxbrew/.linuxbrew/bin/fish

    シェルの変更

    chsh -l [切り替えたいシェルの bin] を実行します。binchsh -lからコピペするといいと思います。
    fishへ切り替えます。

    chsh -l /home/linuxbrew/.linuxbrew/bin/fish

    再ログイン

    一度そのユーザーから離れて再ログインするとfishで入れると思います。

    ユーザーの作成と削除

    デフォルト値の確認

    -Dを付けて実行すると、対象のオプション(ホームディレクトリ設定)などを指定しなかった場合、何が設定されるのかを確認できます。

    useradd -D
    # GROUP=100
    # HOME=/home
    # INACTIVE=-1
    # EXPIRE=
    # SHELL=/bin/sh
    # SKEL=/etc/skel
    # CREATE_MAIL_SPOOL=no

    例えば、ホームディレクトリを変えたい場合は-m-dオプションを、デフォルトシェルを変えたい場合は-sオプションを作る時に指定してあげます。

    ユーザーを作る

    sudo useradd <user-name>
    
    # -m で ホームディレクトリ $HOME/<user-name> を作り
    # -s で デフォルトシェル /usr/bin/fish を指定
    # sudo useradd <user-name> -m -s /usr/bin/fish

    以下のコマンドで表示されれば追加できていると確認できます。

    ユーザー確認

    cat /etc/passwd | grep <user-name>

    ここで「ユーザー名間違えてた」って時は、

    sudo usermod -l <current-name> <new-name>

    で変更できます。もし、ホームディレクトリも作ってしまっているなら、

    sudo usermod -l ... -d /home/<new-name> -m

    上記のように一緒に-d-mを付けることで変更できます。

    sudoer にする

    /etc/sudoers/<user-name>を作ります。

    <user-name> ALL=(ALL) ALL

    上だとsudoを付けた時に毎回パスワードを入力する必要がある設定です。パスワードを省きたい場合は以下も追記します。

    <user-name> ALL=(ALL) NOPASSWD:ALL

    ちなみにこのファイルは、/etc/sudoersにこう書かれていることでsudoers.d内に作ったファイルが読み込まれるようです。

    #includedir /etc/sudoers.d

    ユーザーのパスワードを設定する

    sudo passwd <user-name>
    # Changing password for user test.
    # New password: ***
    # Retype new password: ***

    ユーザーを削除する

    --remove -rを付けるとそのユーザーのホームディレクトリも削除します。

    sudo userdel <user-name>
    # sudo userdel --remove <user-name>

    ssh できるようにする

    ローカル側

    まずはsshするときに使う鍵を作ります。これにはssh-keygenコマンドを使います。

    # ~/.ssh/test/id_rsa に置きたいので作っておきます。
    mkdir ~/.ssh/test
    
    ssh-keygen -f ~/.ssh/test/id_rsa -N '' -t rsa -b 4096 -m PEM -C ''

    ssh-keygenには5つオプションを渡していますが、これはそれぞれ

    • -fは鍵のベース名
    • -Nは鍵のパスワード
    • -tは鍵のタイプ
    • -bは鍵のサイズ
    • -mは鍵の形式(よく分かってません)
    • -Cは公開鍵の後ろに付くuser@host部分

    を指定します。2019年2月ぐらいからこの-m PEMというオプションを付けないと-----BEGIN OPENSSH PRIVATE KEY-----と出力されてしまいうまくsshできないようなので付けるように覚えないと駄目みたいです。
    ちなみにこのオプションを付けるとそれ以前と同じように-----END RSA PRIVATE KEY-----で出力されます。

    これで~/.sshディレクトリにmy-key(秘密鍵)とmy-key.pub(公開鍵)ができたはずです。

    そして、その公開鍵をコピーします。

    cat ~/.ssh/test/id_rsa.pub | tr -d '\n' | pbcopy 

    tr -d '\n'で最後の改行を消す必要があります。(ハマった)

    リモート側

    使いたいユーザーの~/.ssh/authorized_keysにコピーしたものを貼り付けます。

    # .ssh ディレクトリを作る
    mkdir ~/.ssh
    # パーミッションを 600(自分だけが読み書き実行できる) に
    chmod 700 ~/.ssh
    
    # authorized_keys を作る
    touch ~/.ssh/authorized_key
    # パーミッションを 600(自分だけが読み書きできる) に
    chmod 600 ~/.ssh/authorized_key

    接続できるか確認

    以下のようなコマンドで接続できれば完了です。

    ssh -i ~/.ssh/test/id_rsa <user>@<host>
    # [<user>@ip-<host> ~]$

    ローカルの鍵情報をリモートでも引き継ぐ

    GitHubへ普段からローカルでsshを使った方法でpushしたりcloneしている場合、リモート先からだと秘密鍵がないのでそういったことができなくなります。

    そういうときはssh-addコマンドを使います。以下で登録できます。

    ssh-add <リモートで必要な秘密鍵へのパス>
    
    ssh-add -l
    # 登録できていればここにそれが出る

    あとはssh時に-Aオプションを付けてあげるだけです。

    ssh -A ...

    リモート先でもssh-add -lして出てくれば完璧です。

    パスワードが必要な sudo だけど聞かれないようにする

    そういう設定がされてないとsudoコマンドを実行した時にパスワードを入力しないといけません。

    sudo echo 1
    # Password:

    普通にターミナルでそれだけ実行する程度ならそれでも特に問題ないのですが、シェルスクリプトなどで処理の流れを止めたくない時にそれはちょっと困ります。

    sudo -S

    そんなときは-Sまたは--stdinオプションを使います。これでパスワードが標準入力で渡すことができます。

    -S, --stdin read password from standard input

    例えばこんな感じです。

    echo 'passwd' | sudo -S echo 1 2>/dev/null
    # 1

    2>/dev/nullは、sudoを実行したときのPassword:という標準エラー出力のテキストが表示されないように/dev/nullに捨てています。

    fish shell でバージョン Bump する function

    リポジトリはnju33/fish-age

    インストール

    以下でage(読み「あげ」)をインストールします。

    mkdir -p ~/.config/fish/{functions,completions}
    curl -o ~/.config/fish/functions/age.fish https://raw.githubusercontent.com/nju33/fish-age/master/functions/age.fish
    curl -o ~/.config/fish/completions/age.fish https://raw.githubusercontent.com/nju33/fish-age/master/completions/age.fish

    ここまで終わったらfishを再読込します。

    使い方

    バージョンを直接書く

    バージョンを書いた後に--patch,--minor,--majorのどれかを指定します。ちなみに、

    • --patchは最後の数値をインクリメント
    • --minorは真ん中の数値をインクリメント
    • --majorは最初の数値をインクリメント

    するという意味になります。

    age v1.2.3 --patch
    # v1.2.4
    
    age v1.2.3 --minor
    # v1.3.0
    
    age v1.2.3 --major
    # v2.0.0

    gitのタグからバージョンを自動取得

    バージョンを記した Git タグがある場合、コマンドのバージョンを省略するとタグから最新のバージョンを取得し、指定したオプションに合わせて Bump したバージョンを表示します。

    # 以下のようなタグの状態のとき
    git tag
    # v1.1.0
    # v1.2.0
    # v1.2.1
    # v1.2.2
    # v1.2.3
    
    age --patch
    # v1.2.4
    
    age --minor
    # v1.3.0
    
    age --major
    # v2.0.0

    sed で n行目以降だけ表示

    sed -n 2pとかすると1行目だけ取得できますが、2行目以降だけ取得したい場合はどうしたらいいだろうということでした。

    結論としてはこのように実行するでした。

    sed -n '2,$p'

    $pというのは最後の行を指すようです。つまり2行目から最後の行というような意味になるんでしょうか。

    パイプ処理の進歩を表

    これはpvコマンドに依存します。Mac に人は Homebrew を使って以下でインストールできます。

    brew install pv

    pv コマンド

    pvコマンドはcatのようにファイルの内容を表示することができます。そしてそれを別コマンドでパイプ(標準入力)で渡すことで、どれだけ処理が進んだかをプログレスで表示してくれます。

    MySql のリストアの進歩を表示

    以下のようにするとa.dumpのリストアの進歩がどれくらいか見ることができます。

    pv a.dump | mysql --defaults-extra-file=db.cnf db_name
    # 400MiB 0:02:18 [2.89MiB/s] [=========================================>] 100%