カテゴリー別アーカイブ: Tips

Gitの対象から外したいけど、ファイル自体は残しておきたい

問題

  • Gitでバージョン管理していたファイルを残したまま追跡の対象外にしたい。
  • 既に管理対象になっているファイルは、後から.gitignoreにファイル名を追加しても変更の追跡が継続される。

対応方法

一旦ファイルを削除したというcommitを作成して、再度加えることで管理の対象外だと認識させる。

$ git rm --cached want-to-ignore-file
# --cachedオプションがあると、ファイル自体は削除されない。

# 追跡を止めたいファイルを.gitignoreに追加する。
$ EDIT .gitignore

# 必要なら.gitignoreをcommitに含める。
$ git add .gitignore

$ git commit

$ git add want-to-ignore-file

参照

USBにドライブが接続されたら自動的にバックアップを作成したい

目的

USB接続のディスクドライブにバックアップを作成するシェルスクリプトbackup.shがあります。USBにディスクドライブが接続されたら、このスクリプトを自動的に実行するようにしてバックアップの手間を減らしたい。

環境

OS
Ubuntu 16.04

解決策

方針

Ubuntu 16.04を含む最近のLinuxは、デバイスの管理にudevを使用しています。そのため適当なruleファイルを作成すると、デバイスが接続されたり取り外された時に決まったプログラムを実行させることができます。

そこでudevにドライブがUSBに接続されたらバックアップ用のシェルスクリプトbackup.shを実行するルールを作成します。

ただしudevのルールから起動できるプログラムは、短時間で終了する必要があります。バックアップなど終了までに時間がかかるプログラムを実行させようとすると、途中で強制的に終了させられてしまいます1

この制限を回避するために、バックアプをsystemdのサービスとして、udevからはそのサービスを開始するようにします。

systemdサービス

まずバックアップを作成するサービスを定義します。

/etc/systemd/system/backup.service

[Unit]
Description=Backup to Removable USB Drive

[Service]
Type=simple
ExecStart=/root/bin/backup.sh

サービスを定義したら次のコマンドでsystemdに登録します。

# systemctl daemon-reload
# systemctl status backup
* backup.service
   Loaded: not-found (Reason: No such file or directory)
   Active: inactive (dead)

なおsystemdから起動されたプログラムの標準出力は、syslogに記録されると同時にsystemctl status SERVICE_NAMEで確認できます。

udevルール

サービスを登録したら、そのサービスを起動するルールを作成します。

/etc/udev/rules.d/91-backup.rules

ACTION=="add",ENV{ID_BUS}=="ata",ENV{ID_PART_ENTRY_UUID}=="xxxx-xxxx-xxxx-xxxx",RUN+="/bin/systemctl --no-block start backup.service"

デバイスを識別するENVには、udevが認識している値を設定します。認識している値は、udevadm info --name=XXXコマンドで取得できます。

ルールを作成したら、次のコマンドでudevにルールを登録します。

# udevadm control --reload

これでxxxx-xxxx-xxxx-xxxxというUUIDを持つディスクパーティションがataに接続されたらbackup.serviceが起動されます。

参照と脚注

  1. 終了までに時間がかかるプログラムをudevから起動すると途中で強制終了させられる問題を回避するためにバックグラウンドで処理させるようにしても終了させられてしまいます。この問題は、setsidコマンドでセッションIDを変えて、自分がセッションリーダーとなれば終了させられないという記述を見たことがあります。

SATAのリンク速度を制限

症状

ドライブの交換が簡単かと思って、ホットスワップ対応のマウンタを使ってハードディスクをパソコンに取り付けました。

ハードディスクはSATA3.0対応なので、SATAのリンク速度は最高6.0Gbpsです。しかし激しくディスクにアクセスするとたまにエラーが出たり、次のようなログが記録される。

Apr 21 20:00:38 pool kernel: [  891.836436] ata2: limiting SATA link speed to 3.0 Gbps

このログが記録された後は、エラーが出ることはありません。

目的

そこでSATAのリンク速度を自動的に決定しないで、リンク速度を制限(指定)してディスクを接続したい。

対応

SATAのリンク速度は、Linuxのカーネルパラメータlibataで指定することができます。具体的には、/etc/default/grubを編集してカーネルの起動オプションとしてlibataを加えます。

/etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="libata.force=3.0Gbps"

ファイルを編集したらupdate-grubコマンドを実行して編集した内容をgrubに反映させます。

再起動すると、次のように指定した3.0Gbpsでディスクに接続していることがわかります。

$ demesg|grep 'SATA link'
[    1.118975] ata4: SATA link up 3.0 Gbps (SStatus 123 SControl 320)
[    1.119005] ata6: SATA link down (SStatus 0 SControl 320)
[    1.119038] ata3: SATA link up 3.0 Gbps (SStatus 123 SControl 320)
[    1.119065] ata5: SATA link up 3.0 Gbps (SStatus 123 SControl 320)
[    1.119090] ata1: SATA link up 3.0 Gbps (SStatus 123 SControl 320)
[    1.119116] ata2: SATA link up 3.0 Gbps (SStatus 123 SControl 320)

参照

ディスクイメージを簡単にマウント

目的

ディスクイメージのファイルがある。このファイルをマウントして中身を確認・変更したい。

loopデバイスを使ってmountできることは知っているけど、offsetを調べるとか面倒くさい。

方法

kpartxコマンドを使用すると、面倒なoffsetの値をfdiskコマンドなどで調べる必要がなくなる。

kpartxのインストール

kpartxは、Ubuntuではパッケージになっているのでaptコマンドを使ってインストールします。

$ sudo apt install kpartd

ディスクイメージをマウント

まずディスクイメージの各パーティションをkpartxコマンドを使ってloopデバイスに割り当てます。ここでは読み込み専用にしたいので-rオプションを加えています。

$ sudo kpartx -avr disk.img 
add map loop0p1 (252:6): 0 8396800 linear 7:0 2048
add map loop0p2 (252:7): 0 2 linear 7:0 8400894
add map loop0p5 (252:8): 0 8382464 linear 7:0 8400896

次に割り当てたloopデバイスを通して、目的のパーティションをマウントします。

$ sudo mount /dev/mapper/loop0p1 /mnt
mount: /dev/mapper/loop0p1 is write-protected, mounting read-only

$ ls /mnt/
bin   home	      lib64	  opt	sbin  tmp      vmlinuz.old
boot  initrd.img      lost+found  proc	snap  usr
dev   initrd.img.old  media	  root	srv   var
etc   lib	      mnt	  run	sys   vmlinuz

アンマウント

使い終わったらアンマウントしておきます。

$ sudo umount /mnt

$ sudo kpartx -d disk.img 
loop deleted : /dev/loop0

意外と忘れやすいのが、loopデバイスの後片付けです。アンマウントしたら、忘れずにkpartx -dしておきます。

WindowsパソコンでもCapsLockキーをCtrlキーに

目標

WindowsパソコンのCapsLockキーをCtrlキーとして使いたい。CapsLockキーとCtrlキーは交換しないで、これまでのCtrlキーもそのままCtrlキーとする。

すなわちCapsLockキーとCtrlキーの両方をCtrlキーとして、CapsLockキーの機能は不要。

方法

CapsLockキーをCtrlキーにする方法にはレジストリを編集する方法もありますが、Ctrl2capというソフトを使用するのが簡単です。

  1. Ctrl2capをWindows Sysinternalsからダウンロードする。
  2. ダウンロードしたファイルを展開(解凍)する。
  3. コマンドプロンプトを開いて展開したフォルダーに移動する。
  4. ctrl2cap /installコマンドを実行する。
  5. システムを再起動する。
C:\Users\username>cd C:\Users\username\Desktop\Ctrl2Cap

C:\Users\username\Desktop\Ctrl2Cap>ctrl2cap /install

Ctrl2cap Installation Applet
Copyright (C) 1999-2006 Mark Russinovich
Sysinternals - www.sysinternals.com

Ctrl2cap successfully installed. You must reboot for it to take effect.

CapsLockキーを元に戻す

CtrlキーにしたCapsLockキーを元に戻すには、ctrl2cap /uninstallコマンドを実行してCtrl2capを削除して再起動します。

参照

UBUNTUでCAPSLOCKキーをCONTROLキーに

LVM上のファイルシステムを拡張する

状況

  • ルートファイルシステムの残り容量が10%を切ってしまった。
  • ルートファイルシステムはLVM上にあり未割当のブロックはまだ残っている。
  • ルートファイルシステムはext4。
$ df -h
Filesystem                Size  Used Avail Use% Mounted on
/dev/mapper/fs-root      11G  9.7G  486M  96% /
none                      4.0K     0  4.0K   0% /sys/fs/cgroup
udev                      1.9G  4.0K  1.9G   1% /dev
tmpfs                     382M  592K  382M   1% /run
none                      5.0M     0  5.0M   0% /run/lock
none                      1.9G     0  1.9G   0% /run/shm
none                      100M     0  100M   0% /run/user
/dev/sda1                 228M   60M  157M  28% /boot

$ sudo lvdisplay /dev/fs/root
  --- Logical volume ---
  LV Path                /dev/fs/root
  LV Name                root
  VG Name                fs
  LV UUID                jLrK9R-W1PT-zzmx-ep27-IdPY-H2Tf-jcyMXC
  LV Write Access        read/write
  LV Creation host, time , 
  LV Status              available
  # open                 1
  LV Size                10.97 GiB
  Current LE             2809
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           252:0

$ sudo pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda5
  VG Name               fs
  PV Size               37.03 GiB / not usable 1.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              9480
  Free PE               3106
  Allocated PE          6374
  PV UUID               z34vz3-0aVt-wFjy-s81b-c88D-XIOc-Kxqgti

pvdisplayコマンドの結果から未割当のブロック(Free PE)が3106残っていることが分かります。PEのサイズが4MiBなので、3106のPEは約12GiBです。

対応

未割当のブロックが12GiBあるので、この一部(3GiB)をROOT FSのLVに追加します。

$ sudo lvextend -L +3G /dev/mapper/fs-root
  Extending logical volume root to 13.97 GiB
  Logical volume root successfully resized
$ sudo lvdisplay /dev/fs/root
  --- Logical volume ---
  LV Path                /dev/fs/root
  LV Name                root
  VG Name                fs
  LV UUID                jLrK9R-W1PT-zzmx-ep27-IdPY-H2Tf-jcyMXC
  LV Write Access        read/write
  LV Creation host, time , 
  LV Status              available
  # open                 1
  LV Size                13.97 GiB
  Current LE             3577
  Segments               2
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           252:0

これでROOT FSのLVサイズが約14GiBに増えました。しかしこのままでは、ファイルシステムは増加した部分を使用できません。

ファイルシステムがLVM上で拡張した部分を使えるようにファイルシステム自体を拡張します。通常ならばシステムを停止またはアンマウントしてファイルシステムを拡張する必要がありますが、ext4ファイルシステムはライブリサイズに対応しているのでこのまま進めます。

$ sudo resize2fs /dev/fs/root
resize2fs 1.42.9 (4-Feb-2014)
Filesystem at /dev/fs/root is mounted on /; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 1
The filesystem on /dev/fs/root is now 3662848 blocks long.

$ df -h
Filesystem                Size  Used Avail Use% Mounted on
/dev/mapper/fs-root      14G  9.7G  3.3G  75% /
none                      4.0K     0  4.0K   0% /sys/fs/cgroup
udev                      1.9G  4.0K  1.9G   1% /dev
tmpfs                     382M  596K  382M   1% /run
none                      5.0M     0  5.0M   0% /run/lock
none                      1.9G     0  1.9G   0% /run/shm
none                      100M     0  100M   0% /run/user
/dev/sda1                 228M   60M  157M  28% /boot

これでROOT FSの容量が最初の11GiBから14GiBに増え、その結果使用量が75%になりました。

参照

論理ボリュームを拡大するには – Linux Tips @IT

POPサーバに接続できない

症状

POPサーバにCourier mail server(courier-pop)を使用していますが、OSをアップデート(アップグレード)したらPOPサーバにアクセスできなくなってしまいました。

OS
Ubuntu 16.04.2 LTS
パッケージ
courier-pop

syslogには次のようなログが記録されていました。

pop3d: Connection, ip=[::ffff:xxx.xxx.xxx.xxx]
pop3d: authdaemon: s_connect() failed: No such file or directory
pop3d: LOGIN FAILED, user=user_name, ip=[::ffff:xxx.xxx.xxx.xxx]
pop3d: authentication error: No such file or directory

対応

POPサーバにアクセスできない原因は、認証デーモンが起動していないことでした。

$ sudo systemctl status courier-authdaemon
● courier-authdaemon.service - Courier Authentification Daemon
   Loaded: loaded (/lib/systemd/system/courier-authdaemon.service; disabled; ven
   Active: inactive (dead)

そこで認証デーモンを次のように起動させるとPOPサーバに問題なくサクセスできるようになりました。

$ sudo systemctl start courier-authdaemon
# システムが起動した時に自動的にスタートするようにする。
$ sudo systemctl enable courier-authdaemon

$ sudo systemctl status courier-authdaemon
● courier-authdaemon.service - Courier Authentification Daemon
   Loaded: loaded (/lib/systemd/system/courier-authdaemon.service; enabled; vend
   Active: active (running) since Tue 2017-03-28 21:46:42 JST; 13s ago
  Process: 2156 ExecStop=/usr/sbin/authdaemond stop (code=exited, status=0/SUCCE
  Process: 2169 ExecStart=/usr/sbin/authdaemond start (code=exited, status=0/SUC
 Main PID: 2171 (courierlogger)
   CGroup: /system.slice/courier-authdaemon.service
           ├─2171 /usr/sbin/courierlogger -pid=/var/run/courier/authdaemon/pid -
           ├─2172 /usr/lib/courier/courier-authlib/authdaemond
           └─2173 /usr/lib/courier/courier-authlib/authdaemond

参照

courier-authlib: s_connect() failed: No such file or directory – ask ubuntu

[[コマンドの正規表現(後方参照と文字クラス)

bashの[[コマンドでは正規表現を使用できる。正規表現にマッチした部分は後方参照できる。正規表現にはPOSIX形式の文字クラスを指定できる。

[[コマンド

[[コマンドは、多くの場合ifと組み合わせて条件判断に使用されます。この[[コマンドは、[コマンドのただ等しい・大小比較だけではなく=~で正規表現にマッチするか調べられます。

$ [[ "abcdefg" =~ ^abc ]] && echo TRUE
TRUE

正規表現の後方参照

正規表現にマッチした部分は、変数BASH_REMATCHに代入されます。

$ [[ "a1234b" =~ [0-9]+ ]] && echo ${BASH_REMATCH}
1234

変数BASH_REMATCHは配列変数で、添字を指定することで対応する括弧の部分を取り出すことが可能です。

$ [[ "a1234b" =~ a([0-9]+)([a-z]) ]] && echo ${BASH_REMATCH[@]}
a1234b 1234 b

正規表現に文字クラスを使う

正規表現には、文字クラスも使用可能です。ただし次のような制限があります。

  • 文字クラスは選択[]内でのみ使用できる。
  • Perl系の表記方法(例えば数字を表す\d)を使用できない。代わりにPOSIXの表記方法(数字であれば[:digit:])を使用する。
$ [[ "a1234b" =~ a[:digit:]+b ]] || echo FALSE
FALSE
$ [[ "a1234b" =~ a[[:digit:]]+b ]] && echo TRUE
TRUE
$ [[ "a1x2y34b" =~ a([[:digit:]xy]+) ]] && echo ${BASH_REMATCH[1]}
1x2y34

POSIXの主な文字クラスは次のようになります。

文字クラス Perl系 意味
[:digit:] \d 数字
[:xdigit:] \h(Ruby) 16進数での数字
[:alnum:] \w(\wは_を含む) アルファベットと数字
[:space:] \s 改行を含む空白

参照

ログファイルへの書き込みを追いかける

目標

ログファイルに処理記録が書き出される時に、追加された書き込みを見守りたい。

方法

ファイルに追加された書き込みを追いかけるには、tailコマンドに-Fオプションを付けて使用します。

$ tail -F logfile

これで追加された書き込みが標準出力に表示され続けます。

tailコマンドには似たオプションの-fがあります。これも同じく追記された部分が表示されますが、ログローテートなどでファイル名が変更された時の動作が異なります。

オプション ファイル名が変わった時の動作
-F 同名のファイルを開いて追記を追いかける。
-f そのまま追記を待ち続ける。

ログを追いかけている時にファイル名が変わるのは大抵ログローテートによるものなので、新しいログファイルを開いて追記を追いかけれれる-Fオプションを使うことになります。

lessコマンドもある

ログの追記を見守りたいが、同時に過去の書き込みも遡って読みたい時にはlessコマンドが便利です。

$ less logfile

Gキーを押すと常にファイルの最後が表示され、再度Gを押すとその時の最後に更新されます。

そしてFキーを押すとtail -fと同じくファイルに追記されるたびに更新されます。ただし追記から更新までのタイムラグがtail -fよりも少し大きくなります。また-fオプションと同じなので、ファイル名が変更されても同名の新しいファイルには自動では切り替わりません1

脚注

  1. lessのコマンド入力モードでhキーを押してヘルプを表示させれ戻ると、開いていたファイルと同名の新しいファイルの内容が表示されます。逆に元のファイルに戻りたい時にはどうしたら良いのか?

ListViewを含むDialogFragmentの表示を速くする

症状

custom viewを表示するリストをDialogFragmentで表示させようとしたところ、Dialogが表示されるまで二秒以上かかっていました。

どこで時間がかかるのか調べてみると、ListViewに設定したadapterのgetView()メソッドが繰り返し呼び出されていました。

改善方法

そこで同じような例がないかとググってみると、layout_heightをmatch_parentにすればgetView()メソッドの無駄な呼び出しを抑えられるというページ1を見つけました。

そこでDialogFragment内でAlterDialog.Builderに設定するViewを次のようにしてみましたが、最初のgetViewから最後まで2.1秒もかかって効果はありませんでした。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/node_list_view" />
</LinearLayout>
12-27 12:29:22.896 31433-31433/jp.nosuz.* D/DialogList: getView: 0
12-27 12:29:22.916 31433-31433/jp.nosuz.* D/DialogList: getView: 1
...
12-27 12:29:25.028 31433-31433/jp.nosuz.* D/DialogList: getView: 7
12-27 12:29:25.028 31433-31433/jp.nosuz.* D/DialogList: getView: 8

そこでさらに検索するとRelativeLayoutが有効というページ2を見つけました。

このページに従ってLinearLayoutを次のようにRelativeに書き換えると、getView()メソッドを呼び出す回数がぐっと減りました。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/node_list_view" />
</RelativeLayout>

最初のgetViewから最後まで2.1秒かかっていたものが0.07秒になり、表示されるまでの「あれ?」というストレスがなくなりました。

12-27 12:39:58.967 9244-9244/jp.nosuz.* D/DialogList: getView: 16
12-27 12:39:58.977 9244-9244/jp.nosuz.* D/DialogList: getView: 15
12-27 12:39:58.987 9244-9244/jp.nosuz.* D/DialogList: getView: 14
12-27 12:39:59.007 9244-9244/jp.nosuz.* D/DialogList: getView: 13
12-27 12:39:59.007 9244-9244/jp.nosuz.* D/DialogList: getView: 12
12-27 12:39:59.017 9244-9244/jp.nosuz.* D/DialogList: getView: 11
12-27 12:39:59.027 9244-9244/jp.nosuz.* D/DialogList: getView: 10
12-27 12:39:59.027 9244-9244/jp.nosuz.* D/DialogList: getView: 9
12-27 12:39:59.037 9244-9244/jp.nosuz.* D/DialogList: getView: 8

欠点

ただしlayout_heightにmatch_parentを指定しているので、表示する項目数が少ない場合にもDialogが最大の大きさで表示され無駄な空白ができてしまいます。

参照