それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

curl でAPIアクセスのヘッダ毎回指定を設定ファイルを使って省略する

API にアクセスするときHEADER多すぎ

URLとPOST/GETのデータ以外に指定する項目が多すぎて嫌になる。

curl "https://api.example.com/api/v4/settings" \
     -H "X-Auth-Email: takuya@example.com" \
     -H "X-Auth-Key: gfhfdertgfdsertgf" \
     -H "X-Auth-SID: xxxxxxxxxxxxxxxx" \
     -H "Content-Type: application/json"

おおくが、HTTPに沿った認証してないない。認証API叩いて、セッションキーでCookie発行や、Digestで認証してくれたらいいのにな。。。

curlrc でヘッダを省略する

毎回指定しなきゃいけないヘッダは、省略する。

server.com.curlrc

header ="X-Auth-Email: takuya@example.com" \
header ="X-Auth-Key: gfhfdertgfdsertgf" \
header ="X-Auth-SID: xxxxxxxxxxxxxxxx" \
header ="Content-Type: application/json"

curlrc を指定してリクエストする。

curl -K server.com.curlrc  "https://api.example.com/api/v4/settings" 

かなりシンプルになる。

さらにaliasする

curlrc を指定してリクエストする。

alias curl.server.com='curl -K server.com.curlrc  '

これで、大事なことに集中できる。

curl.server.com "https://api.example.com/api/v4/settings" 
curl.server.com "https://api.example.com/api/v4/update" -X PUT --data '{}'

余計なことを考えずにURIとPOSTデータだけに集中できる。

怠惰ですね。もう

f:id:takuya_1st:20170307205131j:plain:w300

API って使いにくいよね。

個人的には、APIが HTTPの jsonで返す意味があんまりないと思うんだけよね。、ぶっちゃけ、GETクエリで検索条件を絞り込めないほうが不便なんだよね。マルっと一括して取ってくるプログラムと、ちまちま実行するUNIXパイプ志向との発想の違いなんだろうけど。欲しいデータだけをGETクエリで指定しちゃうほうが楽だよね。

api もっとシンプルにしてくれたらいいのに、無駄な労力書けて複雑なAPI作って、使う方も複雑になって大変です。

参考資料

curl でよく使う設定をまとめる ~/.curlrc - それマグで!

画像元

https://clubt.jp/product/445475_42465623.html

文字列の長さ順にソートする(awk/sortコマンド組み合わせ)

文字列の長さ順にソートすると美しい。

なんでなんだろうね。アルファベット順よりも文字列長さ順でソートすると、出力がきれいに見えるんだよね。

awk/sort で文字列の長さ順にソートする。

command | awk '{print length() ,$0}' | sort -nr

例えばPATHをソートしてみる

takuya@~$ echo -e ${PATH//:/'\n'}  |  awk '{print length() ,$0}' | sort -nr
26 /Users/takuya/.rbenv/shims
26 /Users/takuya/.pyenv/shims
24 /usr/local/share/npm/bin
24 /Users/takuya/.pyenv/bin
18 /Users/takuya/.bin
15 /usr/local/sbin
14 /usr/local/bin
12 /opt/X11/bin
9 /usr/sbin
8 /usr/bin
5 /sbin
4 /bin

ああ、美しい。

ソートした結果が欲しい時

takuya@~$ echo -e ${PATH//:/'\n'}  |  awk '{print length() ,$0}' | sort -nr | awk '{ print  $2 }'
/Users/takuya/.rbenv/shims
/Users/takuya/.pyenv/shims
/usr/local/share/npm/bin
/Users/takuya/.pyenv/bin
/Users/takuya/.bin
/usr/local/sbin
/usr/local/bin
/opt/X11/bin
/usr/sbin
/usr/bin
/sbin
/bin

うん、美しい。

とくにPATHは文字列が長いほど、優先度が高く、/binなどの共有コマンドを上書きする側になるので、コレが便利。

bcacheでSSDをキャッシュに使ってHDDアクセスを早くしてSSHD的なことをやる

ssd を書込み読み込みキャッシュに使いたい

HDDのアクセスを早くしたい。Writeおせーんだわ。

あれこれ、実装があるけど lvm cache / dm-cache より、bcacheの方が圧倒的に簡単で速かった。

もちろん、こんなことをしなくても、よく使うデータはHDDからメモリにキャッシュされるので、実運用ではメモリに空き容量を増やすのがとにかく先決です。bcacheは趣味ですね。

apt からインストールできる場合

sudo apt install bcache-tools

bcacheのヘッドからインストール

git から取得しインストール

git clone https://github.com/g2p/bcache-tools.git
cd bcache-tools
make
sudo checkinstall    \
--pkgname=bcache-head    \
--pkgversion="1:$(date +%Y%m%d%H%M)" \
--backup=no    \
--deldoc=yes \
--fstrans=no \
--default

bcacheが有効か調べる

bcacheが使えるかどうか確認。

takuya@:~$ sudo modprobe bcache
takuya@:~$ sudo lsmod | grep cache
bcache                193649  0
dm_cache               41114  0
dm_persistent_data     49347  1 dm_cache
dm_bio_prison          13056  1 dm_cache
fscache                45542  1 nfs
mbcache                17171  1 ext4
dm_mod                 89405  17 dm_persistent_data,dm_cache,dm_bufio

使い始める前に用語の整理

  • bcache 此のソフト
  • バッキング・デバイスbacking device キャッシュされる側(通常はHDD)
  • キャッシング・デバイス chacing device キャッシュ側(通常はSSD
  • make-bcache 作成コマンド

バッキングデバイスの指定

今回は、LVM上のVGから100GB のストレージを切り出してブロックデバイスを作成して/dev/sda などの代わりに使う。

これをバッキングデバイスに指定した。

takuya@:~$ sudo make-bcache -B /dev/mapper/data-storage
UUID:           a057b697-795d-450c-8e68-454d6f244b93
Set UUID:       9778b366-5f4c-4947-a180-c66442f2a934
version:        1
block_size:     1
data_offset:        16

キャッシュデバイスの指定

今回はSSD上のLVMから20GB ほど切り出して/dev/sdb などの代わりに使う。

これをキャッシュデバイスに指定した

takuya@:~$ sudo make-bcache -C /dev/mapper/acid-ssd
UUID:           9ac55038-1b95-42fb-bd0f-3b4638476e5d
Set UUID:       aad94dbd-5ded-4d23-bccb-1f3c1f475c48
version:        0
nbuckets:       40960
block_size:     1
bucket_size:        1024
nr_in_set:      1
nr_this_dev:        0
first_bucket:       1

状態を確認する。

バイスが登録されたか調べる。

bacheデバイスが見えるようになったか確認する。

takuya@:~$ ls  -l -R /dev/bcache**
brw-rw---- 1 root disk 253, 0 2017-03-06 18:21 /dev/bcache0

/dev/bcache:
合計 0
drwxr-xr-x 2 root root 60 2017-03-06 18:21 by-uuid

/dev/bcache/by-uuid:
合計 0
lrwxrwxrwx 1 root root 13 2017-03-06 18:21 a057b697-795d-450c-8e68-454d6f244b93 -> ../../bcache0

ここで作成された /dev/bcache0/ が bcacheでキャッシュされた、バッキングデバイス(/dev/sda)などを指している。

バッキングデバイスの状態を確認する

takuya@:~$ sudo bcache-super-show /dev/mapper/data-storage
sb.magic        ok
sb.first_sector     8 [match]
sb.csum         D1AA8DCE13E9B35C [match]
sb.version      1 [backing device]

dev.label       (empty)
dev.uuid        a057b697-795d-450c-8e68-454d6f244b93
dev.sectors_per_block   1
dev.sectors_per_bucket  1024
dev.data.first_sector   16
dev.data.cache_mode 0 [writethrough]
dev.data.cache_state    0 [detached]

cset.uuid       9778b366-5f4c-4947-a180-c66442f2a934

キャッシュデバイスの状態を確認する

takuya@:~$ sudo bcache-super-show /dev/mapper/acid-ssd
sb.magic        ok
sb.first_sector     8 [match]
sb.csum         455541E08344F7F6 [match]
sb.version      3 [cache device]

dev.label       (empty)
dev.uuid        9ac55038-1b95-42fb-bd0f-3b4638476e5d
dev.sectors_per_block   1
dev.sectors_per_bucket  1024
dev.cache.first_sector  1024
dev.cache.cache_sectors 41942016
dev.cache.total_sectors 41943040
dev.cache.ordered   yes
dev.cache.discard   no
dev.cache.pos       0
dev.cache.replacement   0 [lru]

cset.uuid       aad94dbd-5ded-4d23-bccb-1f3c1f475c48

bcache0 にキャッシュデバイスを紐付ける。

sudo bcache-super-show /dev/mapper/acid-ssd  \ 
| grep cset.uuid | awk '{ print $2 }' \
| sudo tee /sys/block/bcache0/bcache/attach

ファイルシステムを作る

ここまでで、bcacheの準備ができたので、後はターゲット(/dev/bcache0)に対して操作をする。

takuya@:~$ sudo mkfs.ext4 /dev/bcache0
mke2fs 1.42.12 (29-Aug-2014)
Discarding device blocks: done
Creating filesystem with 26214398 4k blocks and 6553600 inodes
Filesystem UUID: 5848c161-fd7c-4031-807a-01c56dc7c967
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
    4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

マウントする

sudo mount /dev/bcache0 mnt

測定してみる。

細かいテスト条件を考える暇がなかったのでかなり適当な条件ですが1GB程度の書込みで測定してみました。

単純にbw だけを見てみる。

時間がなくて、細かいテスト条件を考慮できてないので、単純にbw だけを見てみる。 読み込みは今回測定してない

ランダム書込みの測定

バイス 速度(bw)
ssdのみ 242557KB/s
hddのみ 910KB/s
bcache/writethrough 1314KB/s
bcache/writeback 144015KB/s

1GB程度のランダムデータは差が・・・でもまぁ少しは早くなる?

writebackで ssd にだけ書いて hdd にsync 待ちしないならそりゃ圧倒的に早いな

何かに使えそうですよね。

bcacheを使ったときの速度測定

とりあえず、fio でぱぱっと測定。測定条件を全く考慮せず使いまわした・・・次やるときはちゃんと測定条件を考えないと。

[global]
bs=4k
ioengine=libaio
iodepth=4
size=1g
direct=1
runtime=60
directory=/home/takuya/mnt
filename=ssd.test.file

[rand-write]
rw=randwrite
stonewall

fio の結果

takuya@:~$ sudo fio myjob.fio
rand-write: (g=0): rw=randwrite, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=4
fio-2.1.11
Starting 1 process
rand-write: Laying out IO file(s) (1 file(s) / 1024MB)
Jobs: 1 (f=1): [w(1)] [100.0% done] [0KB/1576KB/0KB /s] [0/394/0 iops] [eta 00m:00s]
rand-write: (groupid=0, jobs=1): err= 0: pid=2016: Mon Mar  6 18:44:02 2017
  write: io=78864KB, bw=1314.3KB/s, iops=328, runt= 60008msec
    slat (usec): min=6, max=757302, avg=104.79, stdev=5956.73
    clat (usec): min=78, max=2122.7K, avg=12067.09, stdev=45932.99
     lat (usec): min=89, max=2122.7K, avg=12172.05, stdev=46560.28
    clat percentiles (usec):
     |  1.00th=[  169],  5.00th=[  207], 10.00th=[  251], 20.00th=[ 5600],
     | 30.00th=[ 6688], 40.00th=[ 7136], 50.00th=[ 7392], 60.00th=[ 7648],
     | 70.00th=[ 7968], 80.00th=[ 8768], 90.00th=[11584], 95.00th=[20864],
     | 99.00th=[130560], 99.50th=[144384], 99.90th=[602112], 99.95th=[839680],
     | 99.99th=[2113536]
    bw (KB  /s): min=   14, max= 3093, per=100.00%, avg=1438.70, stdev=699.48
    lat (usec) : 100=0.07%, 250=9.92%, 500=1.09%, 750=0.29%, 1000=0.27%
    lat (msec) : 2=0.31%, 4=1.37%, 10=74.64%, 20=6.77%, 50=2.80%
    lat (msec) : 100=0.22%, 250=1.94%, 500=0.12%, 750=0.14%, 1000=0.04%
    lat (msec) : >=2000=0.02%
  cpu          : usr=0.22%, sys=1.58%, ctx=17090, majf=0, minf=8
  IO depths    : 1=0.1%, 2=0.1%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued    : total=r=0/w=19716/d=0, short=r=0/w=0/d=0
     latency   : target=0, window=0, percentile=100.00%, depth=4

Run status group 0 (all jobs):
  WRITE: io=78864KB, aggrb=1314KB/s, minb=1314KB/s, maxb=1314KB/s, mint=60008msec, maxt=60008msec

Disk stats (read/write):
    bcache0: ios=0/21318, merge=0/0, ticks=0/419156, in_queue=0, util=0.00%, aggrios=0/21324, aggrmerge=0/0, aggrticks=0/260408, aggrin_queue=260408, aggrutil=98.78%
    dm-4: ios=0/21434, merge=0/0, ticks=0/510812, in_queue=510812, util=98.78%, aggrios=0/19972, aggrmerge=0/1474, aggrticks=0/446100, aggrin_queue=446092, aggrutil=98.78%
  sda: ios=0/19972, merge=0/1474, ticks=0/446100, in_queue=446092, util=98.78%
    dm-5: ios=0/21215, merge=0/0, ticks=0/10004, in_queue=10004, util=5.14%, aggrios=0/26443, aggrmerge=0/2553, aggrticks=0/79524, aggrin_queue=79516, aggrutil=7.90%
  sdb: ios=0/26443, merge=0/2553, ticks=0/79524, in_queue=79516, util=7.90%

SSDだけの場合

キャッシュデバイスに利用したSSDからLVMを切り出して使うと次の速度だった。

takuya@:~$ fio myjob.fio
rand-write: (g=0): rw=randwrite, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=4
fio-2.1.11
Starting 1 process
Jobs: 1 (f=1): [w(1)] [100.0% done] [0KB/237.4MB/0KB /s] [0/60.8K/0 iops] [eta 00m:00s]
rand-write: (groupid=0, jobs=1): err= 0: pid=2146: Mon Mar  6 18:47:09 2017
  write: io=1024.0MB, bw=242557KB/s, iops=60639, runt=  4323msec
    slat (usec): min=2, max=1436, avg= 7.19, stdev=13.71
    clat (usec): min=12, max=48210, avg=57.96, stdev=215.17
     lat (usec): min=26, max=48214, avg=65.23, stdev=216.07
    clat percentiles (usec):
     |  1.00th=[   33],  5.00th=[   36], 10.00th=[   37], 20.00th=[   39],
     | 30.00th=[   40], 40.00th=[   41], 50.00th=[   41], 60.00th=[   42],
     | 70.00th=[   43], 80.00th=[   46], 90.00th=[   58], 95.00th=[  231],
     | 99.00th=[  237], 99.50th=[  241], 99.90th=[  684], 99.95th=[ 1160],
     | 99.99th=[ 5856]
    bw (KB  /s): min=169536, max=258520, per=99.67%, avg=241758.00, stdev=30286.36
    lat (usec) : 20=0.01%, 50=83.98%, 100=9.08%, 250=6.55%, 500=0.24%
    lat (usec) : 750=0.05%, 1000=0.02%
    lat (msec) : 2=0.06%, 4=0.01%, 10=0.01%, 20=0.01%, 50=0.01%
  cpu          : usr=11.29%, sys=44.42%, ctx=154698, majf=0, minf=8
  IO depths    : 1=0.1%, 2=0.1%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued    : total=r=0/w=262144/d=0, short=r=0/w=0/d=0
     latency   : target=0, window=0, percentile=100.00%, depth=4

Run status group 0 (all jobs):
  WRITE: io=1024.0MB, aggrb=242557KB/s, minb=242557KB/s, maxb=242557KB/s, mint=4323msec, maxt=4323msec

Disk stats (read/write):
    dm-1: ios=644/251352, merge=0/0, ticks=144/14056, in_queue=14208, util=97.55%, aggrios=644/262180, aggrmerge=0/15, aggrticks=144/18640, aggrin_queue=18752, aggrutil=96.11%
  sdb: ios=644/262180, merge=0/15, ticks=144/18640, in_queue=18752, util=96.11%

HDDだけの場合

takuya@:~$ sudo fio myjob.fio
rand-write: (g=0): rw=randwrite, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=4
fio-2.1.11
Starting 1 process
rand-write: Laying out IO file(s) (1 file(s) / 1024MB)
Jobs: 1 (f=1): [w(1)] [100.0% done] [0KB/1420KB/0KB /s] [0/355/0 iops] [eta 00m:00s]
rand-write: (groupid=0, jobs=1): err= 0: pid=2249: Mon Mar  6 18:50:09 2017
  write: io=54776KB, bw=931985B/s, iops=227, runt= 60184msec
    slat (usec): min=5, max=371161, avg=137.76, stdev=5134.81
    clat (usec): min=101, max=883763, avg=17428.75, stdev=51339.16
     lat (usec): min=126, max=883769, avg=17566.73, stdev=51900.52
    clat percentiles (usec):
     |  1.00th=[  171],  5.00th=[  209], 10.00th=[  223], 20.00th=[ 5600],
     | 30.00th=[ 6752], 40.00th=[ 7200], 50.00th=[ 7456], 60.00th=[ 7712],
     | 70.00th=[ 8160], 80.00th=[ 9280], 90.00th=[17792], 95.00th=[125440],
     | 99.00th=[189440], 99.50th=[261120], 99.90th=[684032], 99.95th=[880640],
     | 99.99th=[880640]
    bw (KB  /s): min=   17, max= 3032, per=100.00%, avg=991.52, stdev=724.89
    lat (usec) : 250=11.17%, 500=0.91%, 750=0.04%, 1000=0.01%
    lat (msec) : 2=0.24%, 4=1.22%, 10=71.24%, 20=7.80%, 50=1.29%
    lat (msec) : 100=0.06%, 250=5.26%, 500=0.48%, 750=0.19%, 1000=0.09%
  cpu          : usr=0.19%, sys=1.14%, ctx=11227, majf=0, minf=8
  IO depths    : 1=0.1%, 2=0.1%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued    : total=r=0/w=13694/d=0, short=r=0/w=0/d=0
     latency   : target=0, window=0, percentile=100.00%, depth=4

Run status group 0 (all jobs):
  WRITE: io=54776KB, aggrb=910KB/s, minb=910KB/s, maxb=910KB/s, mint=60184msec, maxt=60184msec

Disk stats (read/write):
    dm-6: ios=0/14883, merge=0/0, ticks=0/462800, in_queue=473700, util=99.95%, aggrios=0/13821, aggrmerge=0/1075, aggrticks=0/443268, aggrin_queue=450992, aggrutil=99.95%
  sda: ios=0/13821, merge=0/1075, ticks=0/443268, in_queue=450992, util=99.95%
takuya@:~$

writeback にして測定してみる。

witebackを有効にする

takuya@:~$ echo writeback | sudo tee  /sys/block/bcache0/bcache/cache_mode
writeback
takuya@:~$ sudo fio myjob.fio
rand-write: (g=0): rw=randwrite, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=4
fio-2.1.11
Starting 1 process
Jobs: 1 (f=1): [w(1)] [100.0% done] [0KB/151.5MB/0KB /s] [0/38.8K/0 iops] [eta 00m:00s]
rand-write: (groupid=0, jobs=1): err= 0: pid=2341: Mon Mar  6 18:54:19 2017
  write: io=1024.0MB, bw=144015KB/s, iops=36003, runt=  7281msec
    slat (usec): min=1, max=6871, avg=12.32, stdev=16.83
    clat (usec): min=19, max=14755, avg=98.10, stdev=368.31
     lat (usec): min=28, max=14760, avg=110.48, stdev=368.54
    clat percentiles (usec):
     |  1.00th=[   34],  5.00th=[   38], 10.00th=[   39], 20.00th=[   40],
     | 30.00th=[   41], 40.00th=[   43], 50.00th=[   43], 60.00th=[   44],
     | 70.00th=[   46], 80.00th=[   50], 90.00th=[   63], 95.00th=[  157],
     | 99.00th=[ 1864], 99.50th=[ 2480], 99.90th=[ 3152], 99.95th=[ 5024],
     | 99.99th=[13504]
    bw (KB  /s): min=136680, max=161360, per=99.65%, avg=143503.93, stdev=6617.05
    lat (usec) : 20=0.01%, 50=79.82%, 100=14.01%, 250=2.88%, 500=0.19%
    lat (usec) : 750=0.67%, 1000=0.42%
    lat (msec) : 2=1.12%, 4=0.81%, 10=0.06%, 20=0.03%
  cpu          : usr=5.00%, sys=44.67%, ctx=67203, majf=0, minf=7
  IO depths    : 1=0.1%, 2=0.1%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued    : total=r=0/w=262144/d=0, short=r=0/w=0/d=0
     latency   : target=0, window=0, percentile=100.00%, depth=4

Run status group 0 (all jobs):
  WRITE: io=1024.0MB, aggrb=144015KB/s, minb=144015KB/s, maxb=144015KB/s, mint=7281msec, maxt=7281msec

Disk stats (read/write):
    bcache0: ios=223/257488, merge=0/0, ticks=28/26512, in_queue=0, util=0.00%, aggrios=111/132361, aggrmerge=0/0, aggrticks=14/13326, aggrin_queue=13352, aggrutil=95.97%
    dm-4: ios=0/1, merge=0/0, ticks=0/0, in_queue=0, util=0.00%, aggrios=0/1, aggrmerge=0/0, aggrticks=0/0, aggrin_queue=0, aggrutil=0.00%
  sda: ios=0/1, merge=0/0, ticks=0/0, in_queue=0, util=0.00%
    dm-5: ios=223/264721, merge=0/0, ticks=28/26652, in_queue=26704, util=95.97%, aggrios=223/258582, aggrmerge=0/6444, aggrticks=28/15168, aggrin_queue=15116, aggrutil=95.91%
  sdb: ios=223/258582, merge=0/6444, ticks=28/15168, in_queue=15116, util=95.91%
takuya@:~$

writethrough で限界までパフォーマンス上げてみる

シーケンシャルIOの検出・バイパスオフ

takuya@:~$ echo writethrough | sudo tee  /sys/block/bcache0/bcache/cache_mode
writethrough
takuya@:~$ echo 0 | sudo tee /sys/block/bcache0/bcache/sequential_cutoff
0
takuya@:~$ echo 0 | sudo tee /sys/fs/
bcache/ btrfs/  cgroup/ ext4/   fuse/   pstore/

レイテンシ検出オフ

takuya@:~$ echo 0 | sudo tee /sys/fs/bcache/aad94dbd-5ded-4d23-bccb-1f3c1f475c48/congested_read_threshold_us
0
takuya@:~$ echo 0 | sudo tee /sys/fs/bcache/aad94dbd-5ded-4d23-bccb-1f3c1f475c48/congested_write_threshold_us
0

この条件だと、測定結果は次のとおりになった。5%くらいはやい?あんまり変わらないね。

takuya@:~$ sudo fio myjob.fio
rand-write: (g=0): rw=randwrite, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=4
fio-2.1.11
Starting 1 process
Jobs: 1 (f=0): [w(1)] [8.1% done] [0KB/1810KB/0KB /s] [0/452/0 iops] [eta 11m:35s]
rand-write: (groupid=0, jobs=1): err= 0: pid=4873: Mon Mar  6 19:12:02 2017
  write: io=84528KB, bw=1408.7KB/s, iops=352, runt= 60007msec
    slat (usec): min=5, max=16313, avg=86.45, stdev=167.83
    clat (usec): min=77, max=726096, avg=11262.20, stdev=31084.99
     lat (usec): min=85, max=730582, avg=11349.47, stdev=31109.02
    clat percentiles (usec):
     |  1.00th=[  163],  5.00th=[  209], 10.00th=[ 4576], 20.00th=[ 5792],
     | 30.00th=[ 6816], 40.00th=[ 7136], 50.00th=[ 7392], 60.00th=[ 7648],
     | 70.00th=[ 7968], 80.00th=[ 8768], 90.00th=[10944], 95.00th=[18816],
     | 99.00th=[129536], 99.50th=[140288], 99.90th=[544768], 99.95th=[634880],
     | 99.99th=[724992]
    bw (KB  /s): min=   71, max= 3040, per=100.00%, avg=1479.37, stdev=684.76
    lat (usec) : 100=0.06%, 250=6.80%, 500=0.60%, 750=0.18%, 1000=0.13%
    lat (msec) : 2=0.11%, 4=1.35%, 10=79.16%, 20=7.32%, 50=2.14%
    lat (msec) : 100=0.01%, 250=1.91%, 500=0.11%, 750=0.13%
  cpu          : usr=0.73%, sys=3.81%, ctx=17268, majf=0, minf=8
  IO depths    : 1=0.1%, 2=0.1%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued    : total=r=0/w=21132/d=0, short=r=0/w=0/d=0
     latency   : target=0, window=0, percentile=100.00%, depth=4

Run status group 0 (all jobs):
  WRITE: io=84528KB, aggrb=1408KB/s, minb=1408KB/s, maxb=1408KB/s, mint=60007msec, maxt=60007msec

Disk stats (read/write):
    bcache0: ios=0/21070, merge=0/0, ticks=0/242964, in_queue=0, util=0.00%, aggrios=30/21496, aggrmerge=0/0, aggrticks=0/178762, aggrin_queue=178812, aggrutil=99.98%
    dm-4: ios=0/21224, merge=0/0, ticks=0/355520, in_queue=355620, util=99.98%, aggrios=0/21184, aggrmerge=0/51, aggrticks=0/296676, aggrin_queue=296624, aggrutil=99.97%
  sda: ios=0/21184, merge=0/51, ticks=0/296676, in_queue=296624, util=99.97%
    dm-5: ios=60/21768, merge=0/0, ticks=0/2004, in_queue=2004, util=2.88%, aggrios=60/22260, aggrmerge=0/71, aggrticks=0/1788, aggrin_queue=1752, aggrutil=2.54%
  sdb: ios=60/22260, merge=0/71, ticks=0/1788, in_queue=1752, util=2.54%

停止する

stop に 1 を書き込んだらデバイスを停止できる。

takuya@:~$ echo 1 | sudo tee /sys/block/bcache0/bcache/stop
1

もしまた使いたいときは、wipefs でフラッシュする

takuya@:~$ sudo wipefs -a /dev/mapper/acid-cache

主な操作方法

主な操作は /sys/fs 経由で行う。

参考資料

http://www.slideshare.net/nobuto_m/bcachessd-hdd

http://unix.stackexchange.com/questions/225017/how-to-remove-bcache0-volume

http://www.tech-g.com/2015/05/10/bcache-linux-ssd-caching-for-hard-drives-on-debian-jessie/

https://pommi.nethuis.nl/ssd-caching-using-linux-and-bcache/

https://jp.linux.com/news/linuxcom-exclusive/413722-lco20140225

コマンド(lzop)の圧縮展開の進捗どうですかー?(pvコマンドで進捗を見る)

lzop 速くて便利だけど。どこまで終わってるの

lzop って圧縮伸張がそこそこ速くて便利だけど、それでも数十GBやると結構時間がかかるんですよね。

その進捗見たいです。

f:id:takuya_1st:20170306172013j:plain

progress コマンドでは出来ないことがわかった。

progress コマンドも候補に入るらしいので調べたら、lzop は非対応だった。

progress コマンドが対応しているモノ

 cp, mv, dd, tar, cat, rsync, grep, 
fgrep, egrep, cut, sort, md5sum, 
sha1sum, sha224sum, sha256sum, 
sha384sum, sha512sum, adb, gzip, gunzip,
 bzip2, bunzip2, xz, unxz, lzma,
 unlzma, zcat, bzcat, lzcat

lzop ないよ。。うわーん

mv や cp なら簡単なんだけど

mv / cp なら、かわりにrsync --prgoress使うとか。

dst/src だから $(( $(stat -c %s dst ) / $(stat -c %s dst ) )) を見ればいいわけですよね。でも、圧縮伸張の場合は、ファイルサイズが変わるのでどうしたものかと。

pv を見つけた

pv はパイプを通過したファイルサイズをカウントする方法。

そうか、パイプを通せばいいのか。

パイプからデータを読み込んで処理するプログラムなら、入力ストリームを通過したサイズと元ファイルのサイズを比較すればある程度のデータ処理進捗は見えるわけですよね。なるほど

インストール

brew install pv 

実際使ってみた。

$ pv ubuntu.usb.img.lzo | lzop --verbose -d -o out.img -
decompressing <stdin> 
into 4.94GiB 0:00:59 [9.86MiB/s]
 [=======================================>                                                ] 69% ETA 0:00:26

おお、行けるぞコレ。

これで、圧縮伸張などの進捗を表示することが出来ますね。ffmpeg なんかもイケルと思う。ファイルベースのパイプのアクセスって本当に便利ですね。

巨大な mysqlSQLを読み込んでるときとか、ファイルとパイプベースで処理されるコマンドならほぼ全てコレで解決する。

debian/ubuntu なら

apt-get install pv 

簡単です

参考資料

Linuxで『progress』コマンドを使って動いてるcpやmv、tarの進捗状況を調べる | 俺的備忘録 〜なんかいろいろ〜

進捗どうですか? - 時間のかかる処理の進捗を確認 - Qiita

提供元

https://www.ivarch.com/programs/pv.shtml

2017-06-28

若干追記

ページ数の多いPDFのページ指定の読み込みを早くする linearize

pdf の読み込みが遅い?

ページ数の多いPDFがなかなか表示されなくて、イライラしたことがありませんか?

とくに、企業がサイトに設置している取説PDFなどが遅い。全部のダウンロードが終わらないと見えないのはめんどくさい。またスライドなどのPDF資料も全部ダウンロードしてからプレビューが始まったりする。

プレビューで開くのも遅い。AdobeReaderで開くのも遅い。遅くて辛い。

リニアライズする。

調べたら、頭から順に読み込んで表示できないPDFの仕様があるので、これを頭から順に読み込んで表示するように出来ることがわかった。

qpdf --linearize input.pdf output.pdf

これをしておくことで、「ページ指定」した場合にその該当ページがすぐ表示される。表示したときに「先頭ページ」がすぐ表示されるようになる。スキャンしたPDFやスライドなどはこの処理をしておくと非常に快適になったのでメモメモ。

Acrobatなどでも設定ができるらしく、電子書籍のPDFなどは初めからこの設定が済まされていることも多かった。

取扱説明書のリニアライズは企業側に強く求めたい。とくに○○など。

参考資料

QPDF - TeX Wiki

bashの似てて紛らわしいもの() / {} について

サブシェルとグループの違い

  • サブシェル ()
  • グループ {}

サブシェルの大きな特徴は、サブシェルであるということ

サブシェルは、ほぼfork みたいなものだと思ったらいいと思います。

() / { } の違い

  • () はサブシェルを起動し実行する。
  • {} は現在のシェルで実行する。

現在のシェルの中でソースコードを実行するのか、フォークしてフォーク先でソースコードを実行するのかが一番大きな違い。この特徴があるので環境変数の保護や、作業ディレクトリの保護など変数にまつわることを隠蔽できるのが特徴になる。

目次

サブシェルとしての実験

サブシェルとしての特徴を見ていく実験をしておく。

サブシェルが、プロセスを生やしていることを調べる。

コマンド

( sleep 20; )

実行中のプロセス

takuya@Desktop$ pstree  62776
-+= 62776 takuya -bash
 \-+= 63989 takuya -bash
   \--- 63990 takuya sleep 20

コレでわかるとおりです。

bash から bash が枝が生えて、枝bash からsleep が生えています。

グループの場合のプロセスツリー

グループで起動した、この場合のプロセスツリーはどうでしょうか

コマンド

 { sleep 20 ; }

実行プロセス

-+= 64457 takuya -bash
 \--= 64717 takuya sleep 20

グループでは、sleepを直接起動しています。これは

> sleep 20 ;

としているときと全く同じです。

サブシェル時の変数

サブシェルを使う場合、変数は受け継がれる。ただし変更は、戻されない。

これは起動時に変数を引継ぐが、起動後は別のプロセスになるので、変数への更新は反映されない。

takuya@Desktop$ a=1 ; ( echo $a; a=1234; echo $a;   ) ; echo $a   ;
1       # 元シェル $a
1234 # サブシェル内 $a
1      #  元シェル $a

リダイレクトについて

リダイレクトをマトメられる特徴についても見ておく。

() サブシェルと { } グループの 特徴として リダイレクトをマトメられる。

サブシェルはサブシェルとして一つのグループになっているので、リダイレクトはマトメられる

echo 1234 > out.txt
echo 5678 > out.txt
echo 9012 > out.txt

などとするときに面倒だし、() / {} で、マトメて一括リダイレクト指定して、楽に書くことが出来る。

( ) でのリダイレクト

(
echo 1234
echo 5678
echo 9012
) > out.txt

{} でのリダイレクト

またはグループを使うと。

{
echo 1234
echo 5678
echo 9012
} > out.txt

リダイレクトをマトメられるのでちょっと便利に使えるよね。

グループでよくハマること:Syntax Error

グループではまって面食らって「良くわからん」と使うのを断念しちゃう原因にシンタックスエラーがある。

{ } の場合:シンタックスエラー

takuya@Desktop$ { echo 1234; }
1234
takuya@Desktop$ {echo 1234; }
-bash: 予期しないトークン `}' 周辺に構文エラーがあります

開始の{ の直後に文字をつ続けてしまうと、制御構造として解釈されない

ところが、サブシェルの場合はシンタックスエラーにならない (& | ;なとと同等の優先度であるためだと思う。

( ) の場合:シンタックスOK

takuya@Desktop$ (echo 1234; )
1234

この辺も知らないと戸惑う所。

{} / () は関数の定義に使える

理由は良くわからんが、どっちも関数定義に使える。

{} で関数の定義

takuya@Desktop$ func_a () ( echo 1 ;  ); func_a ;
1

( ) で関数の定義!?

takuya@Desktop$ func_a () { echo 1 ;  }; func_a ;
1

気持ち悪さがある。ただ サブシェルが変数をサブシェル内にとどめてくれるので、とても楽にローカル変数を扱う、関数を作ることが出来る

つまり、作業ディレクトリ(wd) を覚えておく、元いた場所に戻すなど、ああいう面倒な作業が一切いらなくなる。

{ } での場合の変数の状況

takuya@Desktop$ pwd ; func_a () { cd ~; pwd  ;    }; func_a; pwd ;
/Users/takuya/Desktop
/Users/takuya
/Users/takuya

( ) での場合の変数の状況

takuya@Desktop$ pwd ; func_a () (  cd ~; pwd  ;    ); func_a; pwd ;
/Users/takuya/Desktop
/Users/takuya
/Users/takuya/Desktop

サブシェルを使う点において同じになるので、少し知ってると便利かもしれない。

まとめ { }( ) の違いはサブシェルを経由するかどうか

サブシェルを経由して、プロセスを生やすことを除き、殆どすべて同じであると思う。

サブシェルの特徴として次のとおりです。

サブシェルとグループに共通する特徴

  • 名前をつけて関数に出来る
  • リダイレクトも纏めてできる。
  • 環境変数は引継がれる。
  • 引継がれる主な変数
    • set / shopt
    • export 済み
    • trap
    • cd / pushd / popd

個人的には () は fork だと思うことにしてる。

今回の一番の驚愕ポイント!!

サブシェルを関数に出来たこと。

myFunc () ( echo aaaaa ) ;  myFunc;

関連記事インデックス

bashの使い方のまとめ記事のインデックス - それマグで!

参考資料

[改訂新版] シェルスクリプト基本リファレンス  ??#!/bin/shで、ここまでできる (WEB+DB PRESS plus)

[改訂新版] シェルスクリプト基本リファレンス  ??#!/bin/shで、ここまでできる (WEB+DB PRESS plus)

S.M.A.R.Tの値をsmartd で監視してメールを送る

HDD のsmart 状態を監視する

HDD のSMARTで値を監視して、ハードウェアの状態が変化したり、故障が近づいたらメール通知しておくことにして、少し安心したい。

準備

sudo apt install smartmontools

smartd の有効化

smartmontoolsを入れたら smartd がついてくる。

sudo systemctl status smartmontools
sudo  systemctl enable  smartd

smartd の設定

設定ファイルは /etc/smartd.conf になる。 以前では /etc/default にあったらしいけど、systemd導入後のDebianだから変わってると思う。

メール設定

さきに、通知が出来る sendmail を設定しておく必要がありそうだったので、設定した→ Deiban/Exim4を設定して、gmailで通知メールを送出する。 - それマグで!

通知の送信先を設定する。

DEVICESCAN -m takuya@example.com

監視するデバイスの設定

ディスクデバイスのパスを指定する。

/dev/sda -a 
/dev/disk/by-uuid/beef5axx-50ed-4ad8-xxx-xxxxxxxxxxxxx -a 

全部見るなら

DEVICESCAN -a

ちゃんとメールが届くかテストする。

DEVICESCAN -M test

実際には、この設定をまとめて書く

DEVICESCAN -a -M test -m takuya@example.com 

ハードディスクの一つずつに設定を書いた場合

/dev/sda -a -M test -m takuya@example.com 
/dev/sdb -a -M test -m takuya@example.com 

みたいにドンドン書く

何か実行させたい時

なにか、実行させたいときは、こんな感じにexec を掛けばいい。

-M exec path/to/file

Debian のデフォルトの場合は

/usr/share/smartmontools/smartd-runner 

が起動することになってた。

此のスクリプトの中で、次のディレクトリにあるファイルが状況に応じて実行されるように設定されてた。

/etc/smartmontools/run.d

実際にやってみた例。

takuya@:~$ sudo -e /etc/smartd.conf
takuya@:~$ sudo  systemctl enable  smartd
takuya@:~$ sudo  systemctl start smartd
takuya@:~$ sudo  systemctl status  smartd
● smartd.service - Self Monitoring and Reporting Technology (SMART) Daemon
   Loaded: loaded (/lib/systemd/system/smartd.service; enabled)
   Active: active (running) since 土 2017-03-04 03:41:43 JST; 1 day 23h ago
     Docs: man:smartd(8)
           man:smartd.conf(5)
 Main PID: 27135 (smartd)
   CGroup: /system.slice/smartd.service
           └─27135 /usr/sbin/smartd -n --interval=172800

 3月 06 03:27:54 acid systemd[1]: Started Self Monitoring and Reporting Technology (SMART) Daemon.
Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.

参考資料

https://wiki.archlinuxjp.org/index.php/S.M.A.R.T.#.E3.83.87.E3.83.90.E3.82.A4.E3.82.B9.E3.81.AE.E7.9B.A3.E8.A6.96

ぱぱっとIP/ドメインを調べるhostコマンド

host コマンドでぱぱっと調べる

host コマンドなるものが有ります。dig みたいだけどdig ほどちゃんとDNSを見れるわけでもないですが、現在使用中のPCから見たドメインとIPの対応はきっちりわかります。

host コマンドの使用例1:Debian GNU/Linux

takuya@:~$ host smtp.gmail.com
smtp.gmail.com is an alias for gmail-smtp-msa.l.google.com.
gmail-smtp-msa.l.google.com has address 64.233.188.109
gmail-smtp-msa.l.google.com has address 64.233.188.108

host コマンドの使用例2:MacOSX

takuya@Desktop$ host t.co
T.co has address 104.244.42.133
T.co has address 104.244.42.5
T.co has address 104.244.42.197
T.co has address 104.244.42.69

host コマンドの使用例3:逆引き

takuya@Desktop$ host 58.188.43.194
194.43.188.58.in-addr.arpa domain name pointer 58-188-43-194f1.osk2.eonet.ne.jp.

IP入れたら逆引きされる。コレは楽

ネームサーバーからの応答を見たい時

-v をつければ、応答内容をちゃんと見れる。

takuya@Desktop$ host -v t.co
Trying "t.co"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47239
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;t.co.                IN    A

;; ANSWER SECTION:
t.co.            1540    IN    A    104.244.42.69
t.co.            1540    IN    A    104.244.42.197
t.co.            1540    IN    A    104.244.42.5
t.co.            1540    IN    A    104.244.42.133

Received 86 bytes from 192.168.2.1#53 in 2 ms
Trying "t.co"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49483
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;t.co.                IN    AAAA

Received 22 bytes from 192.168.2.1#53 in 1 ms
Trying "t.co"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61357
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0

;; QUESTION SECTION:
;t.co.                IN    MX

;; AUTHORITY SECTION:
t.co.            60    IN    SOA    ns1.p26.dynect.net. ops.twitter.com. 1601 3600 600 604800 60

Received 91 bytes from 192.168.2.1#53 in 16 ms
takuya@Desktop$

host で出来ないこと

  • root からたどる
  • ネームサーバー指定

などが出来ないので、そのへんは不便なので、やっぱりdig使ったほうがいいかもしれない。 ただ、digはインストールが必要だったりするので host コマンドも有りかもしれない。

LinxuでHDDの状態を調べる。コマンド

コマンドでSMARTの状態を調べる

HDD の状態を調べるには、S.M.A.R.Tを調べる必要があって、それには smarttools のコマンド一式を使う必要が有ることがわかった。

HDDが異常化か正常化知りたいだけなんだ!

そんなせっかちな人には、此のコマンド PASSED と表示されたOKですね。*1

smartctl -H  /dev/sda -d sat
takuya@:~$ sudo smartctl -H  /dev/sda -d sat
smartctl 6.4 2014-10-07 r4002 [x86_64-linux-3.16.0-4-amd64] (local build)
Copyright (C) 2002-14, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED

では、インストールからいろいろ試してみます。

準備、インストール

apt でぱぱっと入るので楽ちんですね。

sudo apt install smartmontools

早速使ってみる

sudo smartctl -i /dev/sda

-i で指定すると基本的な情報が出てくる

smarttools を見るコマンドは smartctl で、おもに此のコマンドで状態を見る。

takuya@:~$ sudo smartctl -i /dev/sda
smartctl 6.4 2014-10-07 r4002 [x86_64-linux-3.16.0-4-amd64] (local build)
Copyright (C) 2002-14, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF INFORMATION SECTION ===
Model Family:     Western Digital Caviar Green (AF, SATA 6Gb/s)
Device Model:     WDC WD20EZRX-00D8PB0
Serial Number:    WD-WMC4M2XXXXXX
LU WWN Device Id: 5 0014ee XXXXX
Firmware Version: 80.00A80
User Capacity:    2,000,398,934,016 bytes [2.00 TB]
Sector Sizes:     512 bytes logical, 4096 bytes physical
Rotation Rate:    5400 rpm
Device is:        In smartctl database [for details use: -P show]
ATA Version is:   ACS-2 (minor revision not indicated)
SATA Version is:  SATA 3.0, 6.0 Gb/s (current: 6.0 Gb/s)
Local Time is:    Fri Mar  3 17:54:18 2017 JST
SMART support is: Available - device has SMART capability.
SMART support is: Enabled

dm(data mapper) デバイスに対して行うと

DM について smartctl を行うとこんな感じ。ブロックデバイスでも出てくるものと出てこないものがある。かならず物理デバイスに対して行う必要がある。 lvm で dm してて、その元になった /dev/sdX が見えるわけでもない。

takuya@:~$ sudo smartctl -i /dev/mapper/data
smartctl 6.4 2014-10-07 r4002 [x86_64-linux-3.16.0-4-amd64] (local build)
Copyright (C) 2002-14, Bruce Allen, Christian Franke, www.smartmontools.org

/dev/mapper/data-video: Unable to detect device type
Please specify device type with the -d option.

Use smartctl -h to get a usage summary

USB で繋いだドライブも見えないことがある。

USB 経由で繋いだハードディスク・ドライブでは、情報が取れないことがある。

USB経由で繋いでいるドライブなどは TYPEを指定してみる。

USB 経由で繋いだハードディスク・ドライブに実行した失敗例

takuya@:~$ sudo smartctl -a /dev/sda
smartctl 6.4 2014-10-07 r4002 [armv6l-linux-4.4.21+] (local build)
Copyright (C) 2002-14, Bruce Allen, Christian Franke, www.smartmontools.org

/dev/sda: Unknown USB bridge [0x0789:0x0175 (0x103)]
Please specify device type with the -d option.

Use smartctl -h to get a usage summary

USB 経由で繋いだハードディスク・ドライブにTYPE指定した例

TYPE を指定するには -d TYPE_NAME を使うことで値がみられる。

takuya@:~$ sudo smartctl -i /dev/sda -d sat

TYPEに使える値は次の通り。

つかえるあたいは以下の通り。最近はSATAなので -d sat でイケルと思う

ata, scsi, sat[,auto][,N][+TYPE],
usbcypress[,X], usbjmicron[,p][,x][,N], usbsunplus,
marvell, areca,N/E, 3ware,N, hpt,L/M/N, 
megaraid,N, aacraid,H,L,ID, cciss,N, auto, test 

S.M.A.R.Tのオンオフを切り替える

smartctl でSMARTのオンオフを切り替える事ができる。

sudo smartctl -d sat -s on /dev/sda
sudo smartctl -d sat -s off /dev/sda

オフラインテスティングをオン・オフする

sudo smartctl -d sat -o on /dev/sda
sudo smartctl -d sat -o off /dev/sda

Attribute で表示される値のautosaveをオン・オフする

sudo smartctl -d sat -S on /dev/sda
sudo smartctl -d sat -S off /dev/sda

参考資料によると、オフラインテスティングは、ディスクのアイドル時にディスクアクセスを全部カットしてHDDのチェックをするらしい。ただし、ディスクアクセス要求があるとチェックを一旦停止してディスクアクセスを優先し、ディスク・アクセス終了後にディスク・チェックを再開するらしい。この一連の動作はパフォーマンスに影響を与えるかもしれないとのこと。

SMART の状態を表示する

-a で全部の状態を表示することが出来るわけです。

sudo smartctl -a  /dev/sda -d sat

これをつかえば、Windowsな人達もおなじみのデータが見られる。

Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  1 Raw_Read_Error_Rate     0x002f   200   200   051    Pre-fail  Always       -       18
  3 Spin_Up_Time            0x0027   171   168   021    Pre-fail  Always       -       4441
  4 Start_Stop_Count        0x0032   100   100   000    Old_age   Always       -       259
  5 Reallocated_Sector_Ct   0x0033   200   200   140    Pre-fail  Always       -       0
  7 Seek_Error_Rate         0x002e   100   253   000    Old_age   Always       -       0
  9 Power_On_Hours          0x0032   066   066   000    Old_age   Always       -       25262
 10 Spin_Retry_Count        0x0032   100   100   000    Old_age   Always       -       0
 11 Calibration_Retry_Count 0x0032   100   100   000    Old_age   Always       -       0
 12 Power_Cycle_Count       0x0032   100   100   000    Old_age   Always       -       242
192 Power-Off_Retract_Count 0x0032   200   200   000    Old_age   Always       -       204
193 Load_Cycle_Count        0x0032   181   181   000    Old_age   Always       -       58619
194 Temperature_Celsius     0x0022   125   086   000    Old_age   Always       -       22
196 Reallocated_Event_Count 0x0032   200   200   000    Old_age   Always       -       0
197 Current_Pending_Sector  0x0032   200   200   000    Old_age   Always       -       0
198 Offline_Uncorrectable   0x0030   200   200   000    Old_age   Offline      -       0
199 UDMA_CRC_Error_Count    0x0032   200   200   000    Old_age   Always       -       0
200 Multi_Zone_Error_Rate   0x0008   200   200   000    Old_age   Offline      -       0

SMART での提供情報を見る

smart で何が出来るかや設定状況を見る。 各項目ごとに、このHDDにおける、Enabled/supported が見える

Self-test を開始して何分ぐらいたったかもコレでわかる。 また、実行中のテストに何分くらい掛かるかわかる。

takuya@:~$ sudo smartctl -d sat /dev/sda  -c
smartctl 6.4 2014-10-07 r4002 [x86_64-linux-3.16.0-4-amd64] (local build)
Copyright (C) 2002-14, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF READ SMART DATA SECTION ===
General SMART Values:
Offline data collection status:  (0x82) Offline data collection activity
                    was completed without error.
                    Auto Offline Data Collection: Enabled.
Self-test execution status:      (   0) The previous self-test routine completed
                    without error or no self-test has ever
                    been run.
Total time to complete Offline
data collection:        (29040) seconds.
Offline data collection
capabilities:            (0x7b) SMART execute Offline immediate.
                    Auto Offline data collection on/off support.
                    Suspend Offline collection upon new
                    command.
                    Offline surface scan supported.
                    Self-test supported.
                    Conveyance Self-test supported.
                    Selective Self-test supported.
SMART capabilities:            (0x0003) Saves SMART data before entering
                    power-saving mode.
                    Supports SMART auto save timer.
Error logging capability:        (0x01) Error logging supported.
                    General Purpose Logging supported.
Short self-test routine
recommended polling time:    (   2) minutes.
Extended self-test routine
recommended polling time:    ( 293) minutes.
Conveyance self-test routine
recommended polling time:    (   5) minutes.
SCT capabilities:          (0x7035) SCT Status supported.
                    SCT Feature Control supported.
                    SCT Data Table supported.

テストする

smart のHDD状態をチェックする。short と long が選べる。他にも offline, short, long, conveyance, force, vendorなどがある。

sudo smartctl -t short /dev/sda 

参考資料

https://blog.shadypixel.com/monitoring-hard-drive-health-on-linux-with-smartmontools/

https://help.ubuntu.com/community/Smartmontools

S.M.A.R.T. - ArchWiki

*1:正確には、これは最後にテストされて保存された結果から状態を表示しているので完璧とはいえないんだけど

Deiban/Exim4を設定して、gmailで通知メールを送出する。

2022-09-01 追記

Gmailの場合は「アプリパスワード」か「XOAUTH2」に対応させないと、SMTP/IMAPが使えない。

アプリパスワードは手軽だが、認証がめんどくさくなる諸刃の剣

なので、XOAUTH2が出来るように調べた→ https://takuya-1st.hatenablog.jp/entry/2022/03/14/181637

exim4 → XOAUTH2のPostix → 世界 と転送するのがマシだと思う。

メールの設定はめんどくさい→ exim4 で解決

SMTPリレーとかSMTP Outbound port Blocking 25 ( OBP 25 ) だとかさ、めんどくさいんですよね。理解できない人に、「○○が必要で」などと説明するのもめんどくさい。

実は、メール送信は細かい設定や説明を抜きにして簡単に使うことができる。

exim4 を使って localhost:25 宛に送れば外部のSMTPで送信することができる

Gmail 経由で送信する。

というわけで、一番手っ取り早くて、無料で確実なのが Gmail のアカウントを作ってそこから創出するわけですよ。

Debian/Exim4 でGmail経由で送信

DebianだとPostfixではなくExim4が使われていて、これが軽量で、最低限のことは十分にできるので、Exim4でほとんど十分。

Postfix でやる場合

Postfix ではいぜんやったので そちらのログがある

OBP25でもあきらめない。自宅サーバーでPostfixでスパム判定させずメールをリレーで送る方法: gmail の smtp を使った例 - それマグで!

用意するもの

Exim4の確認

exim4 が入っていることを確認する。

# sudo dpkg --list exim4

exim4 の再起動などの方法を確認

systemd 経由の起動状態を確認

sudo systemctl status exim4

systemd 経由で再起動などを確認

sudo systemctl reload exim4
sudo systemctl stop exim4
sudo systemctl start exim4

exim4 の設定反映はコレでもいける

sudo update-exim4.conf

/etc/exim4/update-exim4.conf.conf

設定を以下のようにする。

#  dc_eximconfig_configtype='local'
dc_eximconfig_configtype='smarthost'
dc_other_hostnames='pizero'
dc_local_interfaces='127.0.0.1 ; ::1'
dc_readhost=''
dc_relay_domains=''
dc_minimaldns='false'
dc_relay_nets=''
# -dc_smarthost=''
dc_smarthost='smtp.gmail.com::587'
CFILEMODE='644'
dc_use_split_config='false'
dc_hide_mailname=''
dc_mailname_in_oh='true'
dc_localdelivery='mail_spool'

ポイントは。次の通り。 :: コロンが2つなのはそういうものです。ミスタイプではありません。

dc_smarthost='smtp.gmail.com::587'

メールアカウントの設定

/etc/exim4/passwd.client

## Gmail アカウント
gmail-smtp.l.google.com:my_name@example.com:my_password
smtp.google.com:my_name@example.com:my_password
*.google.com:my_name@example.com:my_password
gmail-smtp-msa.l.google.com:my_name@example.com:my_password
smtp.gmail.com:my_name@example.com:my_password

パスワードをちょっとだけ保護する。

もっとこう、暗号化したり出来たらいいんだけど。 せめて一般ーザーにはパスワード読めないようにしておく

sudo chown root:Debian-exim /etc/exim4/passwd.client
sudo  chmod 640 /etc/exim4/passwd.client

あとはリロードしてテストする

リロード

sudo update-exim4.conf

テスト

メールが送信できるかテストする。

サンプルメールの作成

sendmail を毎回書くのはめんどくさいので、サンプルメールを作っておくことにします。

cat - >  sample-mail.txt
To:takuya@example.com
Subject: Hello, From pizero

Hi, can you see me ?

サンプルメールの送信

cat sample-mail.txt | sendmail -i -t 

crontab の送信先を変える

exim4 を使ってローカル転送をしてる場合は mailto を設定するとcrontab のメールがSMTP経由で届くようになる。

MAILTO=takuya@example.com

ローカル転送をする

ローカル転送を設定する必要がある

/etc/aliases

root:takuya
takuya: takuya+alias@example.com

/etc/email-addresses

takuya: takuya+from@example.com

ローカル転送の確認

takuya@:~$ exim -brw takuya@localhost
  sender: takuya+from@example.com
    from: takuya+from@example.com
      to: takuya@localhost
      cc: takuya@localhost
     bcc: takuya@localhost
reply-to: takuya+from@example.com
env-from: takuya+from@example.com
  env-to: takuya@localhost

このようにして、どのようにメールが転送されていく確認しておきましょう。

Gmail にブロックされることがある。

全く最近はお節介が過ぎてめんどくさい。

SMTP に直接ログインしようとすると less secure だと言われて怒られるので、分かった分かった。その機能オフにしてくれ。オプトアウトしなくちゃいけない。そもそもなにも設定してない時点でオプトインになってるのが面倒なんだが

手作業でファイルを更新するよりdpkg-reconfigureを使う方法もある。

dpkg-reconfigureを使うとログが残りにくくてめんどくさいんですが、マニュアルにするにはこっちのほうが「ウケ」がいいかもしれないですね。

初期設定画面を起動

sudo dpkg-reconfigure exim4-config

初期設定画面のダイアログ形式でちまちま入れていく

ここだけ入れておく

あとは、お好きなようにいれる。 dpkg-reconfigure が終了したら。/etc/exim4/passwd.client を編集する。

個人的な設定メモ

私は、以下のように設定した。

これでGmail経由で通知できる

sendmail 通知が出来るなら、あとは

  • crontab の通知
  • 再起動の通知
  • ジョブ終了の通知
  • ハードウェアの故障・異常の通知

など各種の通知をメールで受けれて便利ですね。

panic log がずっと送出される。

地味にめんどくさかったのがこのパニックログを消す方法

2019-01-01 15:35:09 socket bind() to port 25 for address ::1 failed: Cannot assign requested address: daemon abandoned

これは、私がサーバーのIPv6を止めて以来ずっと定期的に送られてくる。

実はこれ、過去のパニックログが残っていてログローテートしないことが原因らしい。マジすか exim4

/etc/exim4/update-exim4.conf.conf

# before
# dc_local_interfaces='127.0.0.1; ::1'
# after 
dc_local_interfaces='127.0.0.1'

設定を削除した後に、exim4を再起動

sudo update-exim4.conf
sudo service exim4 restart

これで新しいログは出なくなるが、古いパニック・ログが残存しているとそれを送ってくる。

なので、古いログを削除する必要がある。

sudo rm   /var/log/exim4/paniclog

2017-03-22 追記

ローカル配送と、Gmailのメッセージについて追記した。

2019-07-28 追記

「exim4 設定」でキーワードマッチしなかったので、キーワードを見直し

paniclog について記述を追加

参考資料

2020-01-11

GoogleGmailやアレコレを変えたのでこの設定を見直した

gmail と gsuite で若干の差異があるみたい。

iPhoneのSafariがパスワードを確実に学習するには

iOSSafariがパスワードを保存しないことがある。

なんでかずっと考えてたけど、よく考えたらパスワード保存のダイアログの発動条件を思い出したら、form.submit だったかなぁと考えて、保存させる方法に気づいた。SafariのAddonで解決させるしか無いかなと思ってたんだけど。結構にシンプルな解決方法で行けそう。

ドコモIDもちゃんと保存された

f:id:takuya_1st:20170303165429p:plain:w400

WEBページ側のボタンではなく、キーボードを押す

[f:id:takuya_1st:20170303170147p:plain:w250f:id:takuya_1st:20170303170150p:plain:w250

HTML側のボタンはなぜか、JSでアレコレ( xmlhttp や 隠しform ) されてることが多くログインを学習させないことが多いので、キーボード側からSubmitする。

それでも駄目なら Macとつなぐ

それでも駄目なら、iPhoneMacを繋いで、SafariのDevコンソールから、form.submit()ですねぇ。

こんな感じ?

var form = document.createElement('form');
var text = document.createElement('input');
text.value = 'userid'
var pass = document.createElement('input');
pass. setAttribute('type','password')
pass.value = 'my_pass'
form.insertAdjacentElement('beforeend',text)
form.insertAdjacentElement('beforeend',pass)
form.submit()

form[action]先は適当でも学習したり*1する。

もしくは、PCのパスワードをKeychain同期で持っていくしか無い。ああ不便すぎる。

ログインID学習禁止とかいつまでやるんだろうか。

iOS で共有パソコンっていうのも頭悪い話だし。いいかげんセキュリティ関連のテスト項目や実装項目から外してほしいんだけどなぁ。パスワードを学習しない方が、ずっとセキュリティ・コストだよ。キーチェーンは比較的安全なのにな。

*1: たぶん、送信元ページと結果URLが変わってて 200ok が返ってるのが条件だと思う。なので同一ドメインで適当なURLに飛ばせばいい、ログイン前だと殆どのベージでリダイレクト掛かるからコレは楽

Swiftをshebang指定でシェルスクリプト起動!?linuxでも

面白げな記事を見つけました。

新・OS X ハッキング! (166) 開発者でなくても「Swift」は便利に使える | マイナビニュース

#!/usr/bin/swift で swift が起動するというのです。

試してみる。Xcode は入っているので、ターミナルから試してみます。

バージョン確認
takuya@Desktop$ swift --version
Apple Swift version 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1)
Target: x86_64-apple-macosx10.9
takuya@Desktop$

Macで実行してみる

シェルスクリプトとしてSwift を実行してみる。sample.swift ファイルつくって shebang いれて、実行権限をいれる感じですね。

ファイル作って

sample01.swift
#!/usr/bin/swift

import Foundation

let task = Process()


task.launchPath = "/usr/bin/find"
task.arguments = ["."]
task.launch()

task.waitUntilExit()

chmod して

chmod a+x ./sample01.swift

実行

takuya@~$ cd .Trash/
takuya@.Trash$ ~/Desktop/sample01.swift
.
./89-09kotudoro.xls

おおお /usr/bin/find が実行された。 これはシェルスクリプトの代替に pythonruby 使わなくて幸せに慣れそう。node / swift で書くことが出来る。やったね。

どうせならLinuxでも動かしてみる

うちの Debian jessie で swift を動かしてみる。

実験した環境

takuya@:swift$ cat /etc/debian_version
8.6
takuya@:swift$ lsb_release -a
LSB Version:    core-2.0-amd64:core-2.0-noarch:core-3.0-amd64:core-3.0-noarch:core-3.1-amd64:core-3.1-noarch:core-3.2-amd64:core-3.2-noarch:core-4.0-amd64:core-4.0-noarch:core-4.1-amd64:core-4.1-noarch:cxx-3.0-amd64:cxx-3.0-noarch:cxx-3.1-amd64:cxx-3.1-noarch:cxx-3.2-amd64:cxx-3.2-noarch:cxx-4.0-amd64:cxx-4.0-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-3.1-amd64:desktop-3.1-noarch:desktop-3.2-amd64:desktop-3.2-noarch:desktop-4.0-amd64:desktop-4.0-noarch:desktop-4.1-amd64:desktop-4.1-noarch:graphics-2.0-amd64:graphics-2.0-noarch:graphics-3.0-amd64:graphics-3.0-noarch:graphics-3.1-amd64:graphics-3.1-noarch:graphics-3.2-amd64:graphics-3.2-noarch:graphics-4.0-amd64:graphics-4.0-noarch:graphics-4.1-amd64:graphics-4.1-noarch:languages-3.2-amd64:languages-3.2-noarch:languages-4.0-amd64:languages-4.0-noarch:languages-4.1-amd64:languages-4.1-noarch:multimedia-3.2-amd64:multimedia-3.2-noarch:multimedia-4.0-amd64:multimedia-4.0-noarch:multimedia-4.1-amd64:multimedia-4.1-noarch:printing-3.2-amd64:printing-3.2-noarch:printing-4.0-amd64:printing-4.0-noarch:printing-4.1-amd64:printing-4.1-noarch:qt4-3.1-amd64:qt4-3.1-noarch:security-4.0-amd64:security-4.0-noarch:security-4.1-amd64:security-4.1-noarch
Distributor ID: Debian
Description:    Debian GNU/Linux 8.6 (jessie)
Release:    8.6
Codename:   jessie

公式サーバーから swift を持ってくる

ubuntu 14 のものが動いた

wget https://swift.org/builds/swift-3.0.2-release/ubuntu1404/swift-3.0.2-RELEASE/swift-3.0.2-RELEASE-ubuntu14.04.tar.gz \
| tar zxvf - 

REPL でコマンドラインを起動する

Linuxで動きそうなので、せっかくなので対話インターフェースで起動してみる。

./swift-3.0.2-RELEASE-ubuntu14.04/usr/bin/swift

動かす

takuya@:swift$ ./swift-3.0.2-RELEASE-ubuntu14.04/usr/bin/swift
Welcome to Swift version 3.0.2 (swift-3.0.2-RELEASE). Type :help for assistance.
  1> import Foundation
  2> print("Hello Swift Linux")
Hello Swift Linux
  3>

ええ。。。Foundationもあるの。カーソルで戻るなどで若干改行がおかしくなったりするけど問題なさそう。

スクリプトとして実行してみる

ファイル作って

takuya@:swift$ cat  - > sample.swift
#!/home/takuya/swift/swift-3.0.2-RELEASE-ubuntu14.04/usr/bin/swift

import Foundation

let filelist = Task()
filelist.launchPath = "/bin/sh"
filelist.arguments = ["-c", "ls -lS ./"]
filelist.launch()
filelist.waitUntilExit()

実行権限をつけて

takuya@:swift$ chmod 755  sample.swift

実行した

takuya@:swift$ ./sample.swift
合計 115764
-rw-rw-r-- 1 takuya takuya 118528337 12月 14 10:49 swift-3.0.2-RELEASE-ubuntu14.04.tar.gz
drwxrwxr-x 3 takuya takuya      4096  3月  3 16:12 swift-3.0.2-RELEASE-ubuntu14.04
-rwxr-xr-x 1 takuya takuya       226  3月  3 16:34 sample.swift
-rw-rw-r-- 1 takuya takuya       177  3月  3 16:17 test.swift

ちょっと面食らうのが NSTaskProcess でもなく Task だったところかな。

面白い

ちょっとしたシェルスクリプトのファイル操作なども swift で書くことが出来る。プログラミング言語として整ってるので期待したい。Swiftのちょっとしたコードをぱぱっと試せるのは便利ですね。関数の使い方をちょっと試すのに便利そう。内部でコンパイルしてるんだろうけど、、、、

MacのFinderなどプログラムを強制終了・再起動

Mac のFinderを再起動

Finderを再起動するのに

killall Finder

ですが、メニューからも出来るんです。

左上のメニューから再起動する

  • Finder.app を選ぶ
  • Finderを選んだ状態で左上  メニュー
  • Shift キーを押す

f:id:takuya_1st:20170301183207p:plain

なんでも強制終了出来る

finderに限らず、選択したアプリケーションをなんでも強制終了出来る。

f:id:takuya_1st:20170301183723p:plain

うん、手軽で便利ですね。

php のフォークと強制終了

単純なフォーク

<?php
$pid = pcntl_fork();
if ($pid == -1) {
  die('could not fork');
} else if ($pid) {
  // we are the parent
} else {
  // we are the child
  sleep(10);
  var_dump("We are the child:", $pid);
  exit;
}

実行結果

pcntl_wait($status); //Protect against Zombie children
var_dump("END :", $pid);

       \-+= 48201 takuya -bash
         \-+= 49054 takuya php fork.php
           \--- 49055 takuya php fork.php

49054 から 49055 が生えた

2個フォークした場合

<?php
$pid = pcntl_fork();
if ($pid == -1) {
  die('could not fork');
} else if ($pid) {
  // we are the parent
} else {
  // we are the child
  sleep(10);
  var_dump("We are the child:", $pid);
  exit;
}

$pid = pcntl_fork();
if ($pid == -1) {
  die('could not fork');
} else if ($pid) {
  // we are the parent
} else {
  // we are the child
  sleep(10);
  var_dump("We are the child1");
  exit;
}
pcntl_wait($status); //Protect against Zombie children
var_dump("END :", $pid);

実行中の状態

         \-+= 48802 takuya php fork.php
           |--- 48803 takuya php fork.php
           \--- 48804 takuya php fork.php

48802 から 48803, 48804 が生えた

フォークからさらにフォークした場合。

子プロセスから更に子プロセス、つまり孫プロセスを起動したら

<?php
$pid = pcntl_fork();
if ($pid == -1) {
  die('could not fork');
} else if ($pid) {
  // we are the parent
} else {
  // we are the child
  sleep(10);
  var_dump("We are the child:", $pid);
  exit;
}

$pid = pcntl_fork();
if ($pid == -1) {
  die('could not fork');
} else if ($pid) {
  // we are the parent
} else {
  // we are the child
  sleep(10);
  var_dump("We are the child1");
  exit;
}
pcntl_wait($status); //Protect against Zombie children
var_dump("END :", $pid);

この場合、子プロセスが孫より先に死ぬので孫が迷子になってしまう。孤児としてrootプロセスに引き取られる。

なのでちゃんと管理をしなくてはいけない。

fork 先でしっかり終了させる。つまり単純な作業に限定するとか、終了待ちをきちんとする。など

また、子プロセスが生成した子プロセスを見るには再帰して ps -o pid,ppid ax で 子プロセスpidを ppid にもつ孫を探すことになるかもしれない。

fork の注意点

fork を使う前に POSIX fork を知る必要がある。

fork のタイミングでメモリがコピーされますが、リソース(ファイルディスクリプタ)はコピーされると面倒が起きます。MySQLやHTTPなどのコネクションもfd(ファイルディスクリプタ)になってたりするので、fork 先でコネクションしないとエラーになることがある。

fork のコスト

fork するとメモリがコピーされるので、若干負荷が大きい操作になる。そこから先は別プロセスになるので、fork後のメモリの変更(変数の値変更)は別になる。

平行世界が作成されるイメージ

fork の利点

php でも時間がかかる処理は fork 先に任せて、メインは違うことに集中するなどと出来る。

コストは高いが、ジョブを待つだけの メインがあってジョブが来たら fork して仕事をやらせるみたいなことも出来る。

シグナルハンドラ

fork した両方のプロセスでシグナルをハンドリングするには、pcntl_signal_dispatchを入れてあげないといけないみたい

pcntl_signal_dispatch();の代わりに declare(ticks=1) を入れることで解決はしますが、tick を小さくするとパフォーマンスに影響します。

Ctrl+C(SIGINT)を押しても即時反応しない場合とかもdispatchまでいったんキューに入るからだと思います。

pcntl_signal_dispatch はその名前の通り、シグナルキューをそれぞれのハンドラに振り分けるものですね。

<?php


// signal handler function
function sig_handler($signo)
{
  echo "SIGNAL:" . $signo."\n";
  switch ($signo) {
    case SIGTERM:
      echo 'cactch SIGTERM'."\n";
      // handle shutdown tasks
      exit;
      break;
    case SIGINT:
      echo 'cactch SIGINT'."\n";
      exit;
    case SIGHUP:
      echo 'cactch SIGHUO'."\n";
      break;
    case SIGUSR1:
      echo "Caught SIGUSR1...\n";
      echo 'pid:'.posix_getpid();
      echo ' ppid:'.posix_getppid();
      break;
    default:
      echo 'default';
  }

}


pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGINT,  "sig_handler");
pcntl_signal(SIGHUP,  "sig_handler");
pcntl_signal(SIGUSR1, "sig_handler");

pcntl_signal_dispatch();

while (1){

  $a = 0;
  echo 'pid:'.posix_getpid()."\n";

  $pid = pcntl_fork();

  if ($pid===0) {
    // we are the child
    pcntl_signal_dispatch();
    sleep(5);
    var_dump("We are the child:", $pid);
    exit;
  }else{
    pcntl_signal_dispatch();

  }

  pcntl_wait($status); //Protect against Zombie children
  var_dump("waiting is end :", $pid);

}

linux の プロセス管理についてのおすすめ本

Linux のexecコールやfork とプロセス管理がしっかり分かる本だった。

参考資料

pcntl - What's the relation between declare(ticks) and a signal handler in php - Stack Overflow

http://qiita.com/ngyuki/items/a2b9d6d3011528d3becd

スクリーンセーバに表示される時計を大きくしたい

スクリーンセーバーに表示される時計を大きくしたいなと

macOSで打ち合わせ中に、どんどんアイディアが発散して、収拾つかなくなる人が多い。なので、時間を表示しながら打ち合わせで、あっさり解決するんじゃないかと。会議室に時計がなかったり、ホテルや貸し会議室や、外などで時計がないときに話が終わらないよーみたいなときに、無言プレッシャーをかけるのが、時計を置いておいて、チラチラみるという行為。なので時計があると嬉しい。

アイディアソンやハッカソンなどで時間を表示したいときにも便利、時計アプリとかだと画面焼けそうだからつねに写真が動くスクリーンセーバーがいいよね。

時計をMacの画面に常に表示しておいたらいいよね。

いちいち、なにかスクリーンセーバーを探してくるのもめんどくさいので、少し頭をひねった。

出来た

f:id:takuya_1st:20170227153522j:plain

スクリーンの拡大を設定する

コントロール・キー+マウス・スクロールで任意の場所を拡大できるようにする。

f:id:takuya_1st:20170227153518p:plain

右下30%を拡大する

f:id:takuya_1st:20170227154958p:plain

できた。