読者です 読者をやめる 読者になる 読者になる

heyheytower

日々のメモです。誰かのお役に立てれば幸いです。

`bash` でディレクトを移動した時と、コマンドが空の状態で Enter を押したときに `ls` と `git status` を表示する (よく使うコマンド操作の簡略化・自動化)

コマンド操作の簡略化・自動化した結果のスクリーンショット
Pic.1 各種トリガーでls -AFCgit status -sb が実行されたところ

目次

目的

コマンド履歴を確認したところ、いつも同じようなコマンドを実行していることが分かった。
操作の簡略化・自動化できる要素が多分にあったため、その対応を行う。

Op.1 環境確認

$ cat /etc/debian_version
stretch/sid
$ uname -a
Linux calc0 4.4.0-59-generic #80-Ubuntu SMP Fri Jan 6 17:47:47 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"

コマンド履歴の確認

コマンド履歴の達人を目指してみる - ザリガニが見ていた…。のコマンドを参考にさせていただきました。

Op.2 実行頻度の高い上位10コマンド

$ history|sed -e 's/sudo //g'|awk '{ print $2 }'|sort|uniq -c|sort -r|head
   1181 ll
    918 vi
    619 cd
    534 git
    245 apt
    226 l
    211 systemctl
    165 journalctl
    133 rm
    129 cat

方法

できるだけキー入力を省略できるような仕組みと、定期実行でコマンド自動化(cron等)を行う。

bash でコマンドが空の状態で Enter を押したときに lsgit status を表示する

下記の仕組みを用いれば、lsgitの入力を減らすことができると考えた。

コマンドが空であることの判定は、~/.bash_historyの行数の増加をチェックして用いることにした。
当該コードについては次のトピックが関連するので、次のセクションのコードに併記します。

ディレクトリを移動したら自動で lsgit status を表示する

下記を参照しました。

本件は PROMPT_COMMAND を用いることで複数のコマンド実行を実現しており、それを dispatch にて処理するために下記を参照しました。

そして、前述の内容のコードを合わせた下記のコードを.bashrcに追記します。

Code.1 bashディレクトを移動した時と、コマンドが空の状態で Enter を押したときに lsgit status を表示する

# Git repository check
function check_git {
    if [ "$(git rev-parse --is-inside-work-tree 2> /dev/null)" = 'true' ]; then
        echo -e "\e[0;33m--- git status ---\e[0m"
        git status -sb
    fi
}

# cd -> cd + ls
function autols {
    if [ "${AUTOLS_DIR:-$PWD}" != "$PWD" ]; then
        ls -ACF
        check_git
    fi
    AUTOLS_DIR="${PWD}"
}
export PROMPT_COMMAND_AUTOLS="autols"

# Enter -> ls + git status
export HISTCONTROL=ignorespace
COUNT=$(wc -l < ~/.bash_history)
function lsgit {
    COUNT_TMP=$(wc -l < ~/.bash_history)
    if [ "$COUNT" != "$COUNT_TMP" ]; then
        COUNT="$COUNT_TMP"
        return 0
    fi
    
    ls -ACF
    check_git
}
export PROMPT_COMMAND_LSGIT="lsgit"

dispatch () {
    export EXIT_STATUS="$?"

    local f
    # shellcheck disable=SC2153
    for f in ${!PROMPT_COMMAND_*}; do
        eval "${!f}"
    done
    unset f
}
export PROMPT_COMMAND="dispatch"

挙動

まず history の挙動について下記を一読ください。

・先頭がスペースであるコマンドを履歴に残さない方法 > ※はてなブックマークでの補足コメント、有難う御座いました。

1 > export HISTCONTROL=ignorespace
・先頭がスペースであるコマンドを履歴に残さない+重複コマンドを記録しない方法

1 > export HISTCONTROL=ignoreboth

Linuxでコマンド履歴を残さない方法 | 十円玉という名のブログ

~/.bashrcに記載があるのですが、デフォルトではHISTCONTROL=ignorebothの設定です。

今回コード中でexport HISTCONTROL=ignorespaceを指定しており、その点をふまえて本件の挙動を確認してみます。

トップに置いてあるスクリーンショットをここで再掲しますので、合わせて挙動を確認してみてください。

Enter押下時のスクリーンショット

  1. cd ~/.github/を実行する(cd入力がないが、省略する設定を行っている。後述。)
  2. ディレクトリを移動したら自動でlsgit status を表示するgitリポジトリではないのでstatus表示はなし)
  3. cd dotfilesを実行する
  4. ディレクトリを移動したら自動で lsgit status を表示する
  5. wコマンドの実行
  6. wコマンドの結果表示
  7. コマンドが空の状態で Enter を押す
  8. ~/.bash_historyの行数が増えなかったため、lsgit status を表示する
  9. cd .gitを実行する
  10. ディレクトリを移動したら自動で lsgit status を表示する(gitリポジトリではないのでstatus表示はなし)
  11. cd ..の実行
  12. ディレクトリを移動したら自動で lsgit status を表示する
  13. cd ..の実行
  14. ディレクトリを移動したら自動で lsgit status を表示する(注意:HISTCONTROL=ignorebothの条件では、同じコマンドを続けて実行した際は~/.bash_historyの行数が増えないため、lsgit statusが表示されるという動きになってしまい、ここでは"ディレクトリを移動したら"もTRUEなので2回lsgit statusが表示されてしまいます。)

※どこのディレクトリでもgitリポジトリか確認してgit statusを表示するという手もありますが、リポジトリ内でコマンド実行のたびにgit statusが表示されるのは可読性が悪くなると思い、上記のような挙動をコーディングしました。

bash でのcd入力の省略

~/.bashrcshopt -s autocdを追記すると、ディレクトリ名のみが入力された際にcdが自動追記されます。

apt の定期実行

下記2サイトを参考にしました。

3 unattended-upgradesパッケージ
自動アップグレードを実行するパッケージです。
デフォルトだとセキュリティアップデートのみをアップグレードする設定になっています。
アップデート後にシステム再起動が必要な場合に再起動させることも設定できます。
サーバ運用している場合はアップグレード作業が不要になるので便利なツールです。

Ubuntu 16.04: 自動アップデート / アップグレードの設定をする - Narrow Escape

自分の環境ではすでにインストールされていることが確認できたので、/etc/apt/apt.conf.d/20auto-upgradesの内容を確認して、足りない内容を追記しました。(自動実行自体は過去に"ソフトウェアとアップデート"で設定していたのか、インストール時に設定していたのかできていたよう…)

Op.3 aptの自動実行設定の追記

$ sudo apt -y install unattended-upgrades
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
unattended-upgrades はすでに最新バージョン (0.90ubuntu0.3) です。
アップグレード: 0 個、新規インストール: 0 個、削除: 0 個、保留: 0 個。
$ echo 'APT::Periodic::AutocleanInterval "1";' | sudo tee -a /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::AutocleanInterval "1";
$ echo 'APT::Periodic::Download-Upgradeable-Packages "1";' | sudo tee -a /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Download-Upgradeable-Packages "1";

(2017/1/23 追記)
/etc/apt.conf.d/50unattended-upgradesに対して、アップグレード対象をセキュリティだけでなく通常のアップデートも含めるためのコメントインと、更に自分はPPAから外部パッケージのNeovimをインストールしていたので下記を参照にしてレポジトリの追加を行った。

$ head /var/lib/apt/lists/ppa.launchpad.net_neovim-ppa_unstable_ubuntu_dists_xenial_InRelease 
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Origin: LP-PPA-neovim-ppa-unstable
Label: Neovim Unstable
Suite: xenial
Version: 16.04
Codename: xenial
Date: Sun, 22 Jan 2017 20:50:44 UTC
Architectures: amd64 arm64 armhf i386 powerpc ppc64el s390x
$ 
$ head /etc/apt.conf.d/50unattended-upgrades
// Automatically upgrade packages from these (origin:archive) pairs
Unattended-Upgrade::Allowed-Origins {
        "${distro_id}:${distro_codename}";
        "${distro_id}:${distro_codename}-security";
        "${distro_id}:${distro_codename}-updates";
//      "${distro_id}:${distro_codename}-proposed";
//      "${distro_id}:${distro_codename}-backports";
        "LP-PPA-neovim-ppa-unstable:xenial";
};
$ sudo mv /etc/cron.daily/apt-compat /etc/cron.daily/.apt-compat

cronによるコマンドの自動実行

Saba noteを参考に、いつもaptと一緒に実行していた下記のコマンドを一日一回は実行するように設定しました。

$ crontab -l
# min hour day mth wday user command
10 23 * * * ito trash-empty 30 >/dev/null 2>&1
20 23 * * * ito nvim -c "call dein#update()|q" >/dev/null 2>&1

本環境でのファイル削除は、rmの代わりにtrashコマンドを用いています。(CLI削除の場合もゴミ箱に投入され、削除して30日経過したファイルをゴミ箱からも削除する設定にしています。)

Neovim プラグインのアップデートも一日一回できるようになりました。(プラグインアップデート関数の実行を引数として与え、実行後にNeovimを終了しています。)

暗黒美夢王(deo developer)(@ShougoMatsu)さん、いつもありがとうございます!!

まとめ

目的は達成できた。

これでコマンド履歴の確認のトップ10のうち、下記のコマンドの入力回数が減ることが期待できます。

  • ll
  • cd
  • git
  • apt
  • l

以上

"SysVinit" 起動の自作 deb パッケージを "systemd" 対応させる

likana.service のステータス
Pic.1 "systemd" 対応させた自作サービス (likana)

目次

目的

以前作成した deb パッケージが "SysVinit" 起動だったため、自分の環境が "Ubuntu16.04" になったこともあり "systemd" 対応を行った。

方法

"debhelper" の "systemd" 対応

下記記事の通り、debian/controldebian/rules に追記を行いました。

systemd対応¶

systemdの場合は、debhelperのadd onとして、dh-systemdが用意されています。 ですので、まず、 debian/control のBuild-Dependsに、dh-systemdを追記します。

Build-Depends: debhelper (>= 8.0.0), (snip), dh-systemd (>= 1.5), (snip)
次に、 debian/rules の%ターゲットのdhコマンドのオプションとして、systemdを追記します。

%:
dh $@ --with quilt,systemd
systemd用の設定ファイルは、upstartと同様テンプレートは用意されていません。debian/<パッケージ名>.serviceとして用意します。debian/yrmcds.service として作成します。

上記のみで、あとはdh-systemdが良きように設定してくれるのですが、これだけではpurge(apt-get purge)の時に残骸が残ります。 ですので、 postrm で下記のファイルを削除します。

/etc/systemd/system/yrmcds.service
/etc/systemd/system/multi-user.target.wants/yrmcds.service
/var/lib/systemd/deb-systemd-helper-enabled/yrmcds.service.dsh-also
/var/lib/systemd/deb-systemd-helper-enabled/multi-user.target.wants/yrmcds.service
/var/lib/systemd/deb-systemd-helper-masked/yrmcds.service


How to create a Debian package of support to sysvinit, upstart, systemd — ペンギンと愉快な機械の日々

deb パッケージの Ubuntu16.04(xenial) 対応

下記に記載がありますとおり、debian/changelog の対象ディストリビューション記載を変更します。

That format is a series of entries like this:

 package (version) distribution(s); urgency=urgency  
      [optional blank line(s), stripped]  
   * change details  
     more change details  
      [blank line(s), included in output of dpkg-parsechangelog]  
   * even more change details  
      [optional blank line(s), stripped]  
  -- maintainer name <email address>[two spaces]  date  

package and version are the source package name and version number.

distribution(s) lists the distributions where this version should be installed when it is uploaded - it is copied to the Distribution field in the .changes file. See Distribution, Section 5.6.14.

Debian Policy Manual - Source packages

実際は dch -v 1.5-2ppa などを実行して debian/changelog を編集します。

下記コードでは、"1.5-2ppa" のバージョンから "xenial" に変更されていることがご覧いただけるかと思います。

Code.1 debian/changelog

likana (1.5-2ppa) xenial; urgency=low

  * Set up a systemd.

 -- ito <maijou2501@gmail.com>  Thu, 15 Sep 2016 23:43:45 +0900

likana (1.4-1ppa) precise; urgency=low

  * Fix, typo and binary path.

 -- ito <maijou2501@gmail.com>  Fri, 16 Sep 2016 23:41:21 +0900

これで "PPA" にてバイナリが作成される際のディストリビューション指定が完了しました。

debian/package.service の作成

"systemd" の "Unit" を書く前にそもそも "systemd" の仕組みが分かっていなかったので、先ほどの記事や下記の記事で理解を深めた。

自分の場合でも、/etc/init.d/package の内容をもとに、"service" の "Unit" を作成した。

"systemd" での設定ファイルについて

設定ファイルは同じ /etc/default/package を用いて良いようだ。

SystemdForUpstartUsers - Ubuntu Wiki

Existing sysvinit style scripts read configuration in the form of variable assignments from a file under /etc/default. A policy decision is needed on whether systemd units will do the same.


systemd - Ubuntu Wiki

しかし下記の記事内容のとおりで変数の扱いが違うようで、/etc/default/package の中で変数の代入に変数を用いないようにした。

systemd の Environment / EnvironmentFile では変数展開できません - Qiita

"systemd" での /etc/default/package への配置を Makefile にて対応

"SysVinit" の場合、debian/package.default を利用することで、/etc/default/package へ配置できていたが, 自分の設定が足りないせいなのか "systemd" を用いた場合に配置がうまくいかなかった。

正しい対応ではないかもしれないが、Makefile の "install" ルールにて対応した。

Code.2 "Makefile" より抜粋

-snip-
install:
-snip-
        test -e ${DESTDIR}/etc/default && install -m 644 -g root -o root debian/${NAME}.default ${DESTDIR}/etc/default/${NAME}
-snip-

debian/postrm への追記

先ほどの記事を参考に、削除すべきファイルを設定した。

自分の場合は debian/package.udev を利用しているので、/etc/udev/rules.d/*package.rules を削除する設定を追加した。

"systemd" の "service" の実行を "input" グループで行う

自作のサービスでは /dev/input/event* をオープンするもので、"systemd" では "service" のグループを "input" に設定しないといけないようであった。

Users and groups - ArchWiki

Op.1 オーナーとパーミッションの確認

$ ls -l /dev/input/
合計 0
drwxr-xr-x 2 root root     100 10月 30 23:19 by-id
drwxr-xr-x 2 root root     100 10月 30 23:19 by-path
crw-rw---- 1 root input 13, 64 10月 30 23:19 event0
crw-rw---- 1 root input 13, 65 10月 30 23:19 event1
crw-rw---- 1 root input 13, 66 10月 30 23:19 event2
crw-rw---- 1 root input 13, 67 10月 30 23:19 event3
crw-rw---- 1 root input 13, 68 10月 30 23:19 event4
crw-rw---- 1 root input 13, 69 10月 30 23:19 event5
crw-rw---- 1 root input 13, 70 10月 30 23:19 event6
crw-rw---- 1 root input 13, 71 10月 30 23:19 event7
crw-rw---- 1 root input 13, 72 10月 30 23:19 event8
crw-rw---- 1 root input 13, 73 10月 30 23:19 event9
crw-rw-r-- 1 root input 13,  0 10月 30 23:19 js0
crw-rw---- 1 root input 13, 63 10月 30 23:19 mice
crw-rw---- 1 root input 13, 32 10月 30 23:19 mouse0

まとめ

目的のとおり、以前作成した deb パッケージ(likana)の "systemd" 対応を行うことができた。

※ "PPA" での公開 " likana : kyohei ito "