それマグで!

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

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

NginxでContent-Typeを指定する。

nginx で Content-Typeを指定する。

すぐに皆が思いつきそうな設定例はこれ。わりと何処にでも書いてある。だけど、、、本当にコレがベターなの?

      location ~ \.mkv$  {
       default_type video/mp4;
      }

types がある。

マニュアル読んでると types がった。

types {
  video/mp4 mkv;
}

types は server や location コンテキスト内部にも記述ができる。

server {
  location ~ / {
    types {
      video/mp4 mkv;
    }
  }
}

ちなみに、if の中で default_type は出来ないので、if 文は使えない。

nginx って if 文で一見すると読みやすそうだけど、設定していくと if 文は悪 if is Evil とか書いてる文書にぶち当たるし、 if の中で出来ることは限られる。

nginx って意外と使いにくい。

参考資料

http://nginx.org/en/docs/http/ngx_http_core_module.html#types

find コマンドでgit フォルダを無視したい(ただし.gitフォルダは表示したい

find コマンドで gitがズラッと並ぶの不便

ああ、、、、要らないよこんなの。。。

takuya@pages$ find
takuya@pages-sample$ $(which find ) -type f
./.git/COMMIT_EDITMSG
./.git/config
./.git/description
./.git/FETCH_HEAD
./.git/HEAD
./.git/index
./.git/info/exclude
./.git/logs/HEAD
./.git/logs/refs/heads/master
./.git/logs/refs/remotes/origin/master
./.git/objects/02/399e371c5d109e1c8221c74c9135a0c069d8fb
./.git/objects/07/968b16567a3c9b2eae0a3749eeb4f16d90d16c
./.git/objects/0d/e9c93edbe76efb6f0deedb1078746667460c0e
./.git/objects/0e/5e7135586f82d8b80f243e18c57443fca70b00

not マッチを使う。

find -mindepth 1 -not -iwholename *.git/*

not マッチをして .git を無視した例

takuya@pages-sample$ find
/Users/takuya/.bin/find -mindepth 1 -not -iwholename *.git/*
./.git
./.gitignore
./.gitlab-ci.yml
./public
./public/index.html
./README.md

object は要らないけど、hookやconfigは見たいんだ。

find の -not は重ねて書くと、or 条件で積み重ねてていく。 というか、マッチしたものを除外するので正確には、-not 条件を 足す感じ

find -mindepth 1  \
-not -iwholename *.git/objects* \
-not -iwholename *.git/logs* \
-not -iwholename *.git/refs* \
-not -iwholename *.git/*HEAD* \
-not -iwholename *.git/in*

適度に選ぶ。

ガッツリ.git 消しちゃうのも不便。

.gitignroe.git/config とか .gitlatb-ci.yml とかもあるので適度に必要なものだけを残して、見ても仕方ないものを消せる。

find に ignroe scm っていうオプションがアレばいいのにね。

関連記事

git 萌え本

わかばちゃんと学ぶ Git使い方入門〈GitHub、Bitbucket、SourceTree〉

わかばちゃんと学ぶ Git使い方入門〈GitHub、Bitbucket、SourceTree〉

vimでphp.iniの設定ファイルを開くときのハイライトさせるファイルタイプ設定

vim で iniファイルのハイライト

ini ファイルは dosini という名前でデフォルト登録されている。

:set ft=dosini

モードラインを書いておく。

ファイルの1行目に書いておけば、モードラインとして設定を拾ってくれるので多少ファイルの中身とファイルの拡張子が合わないときでも便利。

 # vim: ft=dosini ts=2 sw=2 sts=2 sr noet:

こうしておけば、php-fpm.conf とか iniのくせに conf 拡張子になってるものにも対応できる

ちなみに、php.iniの場合は コメントアウトの文字が # じゃなくて ; なので注意

; vim: ft=dosini ts=2 sw=2 sts=2 sr noet:

設定例

f:id:takuya_1st:20180225030816p:plain

関連資料

vim のモードラインでvim設定(タブなど)をファイルに書く - それマグで!

参考資料

http://www.gregfreeman.io/2011/vim-syntax-highlighting-for-php-fpm-conf-files/

2018年8月21日追記

末尾に、 「:」が抜けていたので修正。

vim スタイル

ln -s で相対シンボリック作成のやりかたと解説。

ln -s で失敗した経験ありますよね?

/var/www/log/index.php から /var/www/html/index.php へリンクする場合。こういうときに、相対パスをぱぱっと作れたら嬉しいでしょ?

でも、ぱぱっと作れなかったり、相対パスを作ったつもりがリンク切れてたり。。そして、失敗を繰り返してしまう。

最後には、諦めてフルパスでリンク書いてたり。しませんか?

ところが、フルパスだとバックアップフォルダ移動後にリンクが壊れたりする。

相対パスでリンクすると、あとで楽だもんね。

だから基本的に相対パスで書きたいよね?うん。だよね???だよね???

というわけで、相対パスシンボリックリンクの作り方。

お急ぎの人は

記事の最後へどうぞ。

次のようなリンクを作ってみます。

ファイルをリンクする場合に相対パス絶対パスで作ってみます。

絶対パスなら次のように

ln -s /var/www/log/index.php  /var/www/html/index.php

相対パスなら次のように・・・?

ln -s ./index.php  /var/www/html/index.php

ん?相対パスのスタートはどこだ?誰から見た相対パスを入れるんだ?

相対パスは、宛先ファイルから見た相対です。

/var/www/log/index.php から /var/www/html/index.php へリンクする場合。

つまり宛先からみた、相対パスをいれる。

ln -s ../log/index.php  /var/www/html/index.php

相対パスの求め方。

作りたいリンクから見た相対パスを1番目に指定する。

ln -s は2番目の引数を考えてから、1番目の引数を考える。 ところが一般的なコマンドは目的地(2番目)のコマンドの内容を考える。なので、思考のパターンが逆になる。

このへんがいつもわかりにくいミスする原因なんだと思う。

カレントディレクトリ。

ln で作成するリンクのファイルからみて相対パスにカレントディレクトリは考えない。

作成するリンクと、作業中のカレントディレクト

作成するリンクファイルはワーキングディレクトリからの相対パスで指定することが出来る。

cd /var/www/
ln -s ../log/index.php  ./html/index.php

ここで、 次に注意する。

  • ../log/index.php作成するリンクから見た 相対パス
  • ./html/index.php作業ディレクトリからみた 相対パス

引数それぞれで、相対パスの元が異なるの。ここがよくミスしたり誤解が増えるポイントだと思うんですよね。

ポイントのおさらい

  • 第1引数  作成ファイルから見た 相対パス
  • 第2引数 ワーキングディレクトリからみた 相対パス

相対パスの求め方

たとえば realpath を使ってみる。

$ realpath --relative-to=$( dirname /var/www/html/index.php)  /var/www/log/index.php
../log/index.php
$ ln -s ../log/index.php  /var/www/html/index.php

コレらを併せて。

ln -s $(realpath --relative-to=$( dirname /var/www/html/index.php)  /var/www/log/index.php)  /var/www/html/index.php

面倒くさい。

realpath と ln -s を組み合わせるのは本当に面倒くさい

-r オプション最強

この目的のためにあるのが、r オプション

ln -sr で解決

相対パスを自動て解決してくれるのが -r オプション。まじでコレ付けるだけで解決する魔法のオプション

ln -s -r /var/www/log/index.php /var/www/index.php

r 付けるだけ これで今の理屈を全部やってくれる。知らなかったら絶対に損するオプション。

どこで活躍する?

バージョンごとにフォルダ変えたり、dockerfile とか

sites-enablesites-available など 設定ファイルの有効・無効をリンクで切り替える構成にするときにすごく重宝する。

-r オプションが無いんだけど怒!!

そういうときは、困りますよね。 ワーキング・フォルダを移動します。 リンクを作成するフォルダに cd してから相対パスで指定するとうまくいきます。

cd /var/www/html  ## リンク作成するディレクトリへ先にcd します。
ln -s ../log/index.html ./index.html

ディレクトリのリンクの場合も同じです。

関連資料

bashでファイルパスの相対パスを得る(絶対パスの取得やパスの正規化も)/realpath利用 - それマグで!

参考資料

man ln

関連アイテム

ファミコンミニ リンクの冒険

ファミコンミニ リンクの冒険

f:id:takuya_1st:20180225020756p:plain:w200

Systemd 時代のresolv.conf

/etc/resolv.confがない。

驚いた、Resove.conf がなくなってるんですよ

systemd 管理下に置かれた

/etc/systemd/resolved.conf

代わりに、次のファイルがが出来た

昔からある resolv.conf は systemd が管理してしまう。

もしかしてリンク?

takuya@ubuntu01:~$ ll /etc/resolv.conf
lrwxrwxrwx 1 root root 39 11月  8 22:56 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf

なんてことだ。。。。なんて面倒くさいことをやってくれるんだ。。。

リロードが必要

DNSなど名前解決設定を更新したら、sysd でリロードが必要だった。

systemctl restart systemd-resolved.service

ナゼこんなことになってるのか。

resolv.conf は systemd の unit になった。 ネットワーク設定に従ってDHCPで書き換えることが多くて、ネットワークのターゲットに従う。

個人的には、ネームサーバーなんて固定で良いんだけどなぁ。

ruby のDateTimeを30分(1800)すすめる

ruby のDateTimeの時刻をすすめる

datetime + 1800/(24*60*60).to_f

ただ時間をすすめるだけだと、単純にInt秒数を足すことが最短経路だった。

いちいち AcrtiveSupport 的なものに頼るのも面倒な話だ。だけどもう少し楽にならないのかな。

ad

MouseEvent Path が便利

とりあえずマウスイベントをデバッグしたり調べたいとき

document.body.addEventListener('click',function(e){ debugger ; })

e.path クリックした要素から、body での各パスが入ってる。 バブリングを順番に辿れるので便利。

path を見れば途中の経路になにがあるのかよく分かる。

path
eventPhase
isTrusted
bubble

ただし、イベントリスナーを管理するのはめんどくさいだろうな。

エレメントにハンドラつけてたら、エレメントをコピーしたらハンドラを一掃できて便利だしな。

複数Gmailを手軽に管理する方法。スマホ設定も通知も迷惑メール対策がぐっと楽になるテクニック

Gmailのアカウントが増えすぎて困る

Gmailのアカウントが増えすぎ。

常時に大量にメールチェックするのがもう無理。っていうかメールは通知以外で殆ど使わないと思うんだ。

そうだフォワードしよう

メールは転送してフォワードしてしまえば良いのではないか。

メインのメアドに全部転送することにした。

メインのメアドはGSuite(Google Apps)を開始当初から使ってるので10年くらい。そこに全部持ってくることにした。

f:id:takuya_1st:20180222031206p:plain

転送設定

Googleアカウントには、転送を設定する。

f:id:takuya_1st:20180222003058p:plain

返信どうするの?→1箇所で全部返信できるよ

メインのメアドから返信出来ます。Gmailどうしで転送設定するとGmailではFromもそのまま使えるようになってて、超便利!

スパムフィルタがあって便利

GMailから転送するとスパムフィルタのフィルタ結果のメールしか転送されない。

つまり、古くからの単純転送とは違ってフィルタ済みのメールが転送される。

そのためずっと転送されるメールが少ない。

だから、メインのメアドのメールボックスが爆発する心配もあまりない。

f:id:takuya_1st:20180222031737p:plain

iPhone / iPad ( iOS ) の設定が楽

スマートフォンにメールボックスの設定や、通知設定をするとき、1つのアカウントだけを設定するので楽。複数アカウントを設定するのは機種変更時や端末追加でたくさん登録が必要になって面倒くさい。

f:id:takuya_1st:20180222031928p:plain

結論

Gmail複数アカウントを束ねるメアドを決めて使う。

転送だけじゃなく、「権限の移譲」ということで複数人でアカウント権限をシェアして使うことも出来る。

問い合わせメールや返信メールは権限の移譲で、自分のメアドなら転送設定が楽。

これでGmailのメアドを無限に増やせるんだけど、そのうち制限が掛かりそうなのでいまのうちにたくさんメアドとっておくほうが良いかもね。

参考資料

権限移譲

転送設定

Hacking Gmail (English Edition)

Hacking Gmail (English Edition)

bashの補完のcompgenでハイフン(ダッシュ/-)の引数を補完する

問題点

-list から -listDevice のようなcompletion が出来なくて、invalid option なっちゃう。

$ networksetup -list<TAB>
compgen 無効な引数です

キーワードの補完ができない。

ハイフンを付けた引数を補完するときは

compgen にハイフンをハイフン( -- )で渡してあげる。

compgen -W $list -- ${COMP_WORDS[COMP_CWORD]

-list -listdevice などのハイフンが入ったオプションを補完しようとすると、無効なオプション として compgen がwordとして compgen自身へのオプションとして持っていっちゃう

つまり

compgen -W ワードリスト -- '-list'

のようにしてあげないと、 -list から -listDevice のようなcompletion が出来なくて、invalid option なっちゃう。

compgen の使い方

compgen の使い方を見ておくと、次のようになっている。

compgen: compgen [-abcdefgjksuv] [-o option]
 [-A action] [-G globpat] [-W wordlist]  [-F function] 
[-C command] [-X filterpat] [-P prefix] [-S suffix] [word]
    オプションに基づいた補完候補を表示します。

    シェル関数の中で補完候補を生成するために使用するように意図されています。
    オプション引数 WORD が与えられた場合、WORD に対して一致した候補が生成
    されます。

    終了ステータス:
    無効なオプションが与えられるかエラーが発生しない限り成功を返します

サンプル

-listXXXX が大量にあるコマンド補完する例です。

#!/usr/bin/env bash 

### 補完関数。
_takuya_networksetup (){
  curr="${COMP_WORDS[@]}"
  prev="${COMP_WORDS[$COMP_CWORD-1]}"
  cmd_name=networksetup

  if [[  $prev =~ $cmd_name ]] ; then 
      sub_command_list=$( networksetup -h | /usr/bin/grep networksetup | awk '{print $2}' )
      COMPREPLY=( $(compgen -W "$sub_command_list" -- ${COMP_WORDS[COMP_CWORD]}  ) ) 
    fi
}
complete -F _takuya_networksetup networksetup

参考商品

アタック Dash Button

アタック Dash Button

mysqldumpがなんかメッセージ吐くので、アップグレード

mysql の自動バックアップがWarnings

なんかエラー吐くので、しらべたら、MySQLMariaDB でしかもバージョンアップが終わってるのにテーブルが古いってことらしい

mysqldump: Couldn't execute 'show events': Cannot proceed because system tables used by Event Scheduler were found damaged at server start (1577)
mysqldump: Couldn't execute 'show events': Cannot proceed because system tables used by Event Scheduler were found damaged at server start (1577)

アップグレードコマンドを叩いてみた

root@acid: # mysqlcheck --no-defaults --check-upgrade --all-databases  --auto-repair -p 
Enter password:

そのご、アップグレードする。

root@acid:~# mysql_upgrade -p
Enter password:
MySQL upgrade detected
Phase 1/7: Checking and upgrading mysql database
Processing databases
mysql
mysql.column_stats                                 OK
mysql.columns_priv                                 OK
mysql.db                                           OK
mysql.event                                        OK
mysql.func                                         OK
mysql.gtid_slave_pos                               OK
mysql.help_category                                OK
mysql.help_keyword                                 OK
mysql.help_relation                                OK
mysql.help_topic                                   OK
mysql.host                                         OK
mysql.index_stats                                  OK
mysql.innodb_index_stats                           OK
mysql.innodb_table_stats                           OK
mysql.ndb_binlog_index                             OK
mysql.plugin                                       OK
mysql.proc                                         OK
mysql.procs_priv                                   OK
mysql.proxies_priv                                 OK
mysql.roles_mapping                                OK
mysql.servers                                      OK
mysql.table_stats                                  OK
mysql.tables_priv                                  OK
mysql.time_zone                                    OK
mysql.time_zone_leap_second                        OK
mysql.time_zone_name                               OK
mysql.time_zone_transition                         OK
mysql.time_zone_transition_type                    OK
mysql.user                                         OK
Phase 2/7: Installing used storage engines
Checking for tables with unknown storage engine
Phase 3/7: Fixing views from mysql
Phase 4/7: Running 'mysql_fix_privilege_tables'
Phase 5/7: Fixing table and database names
Phase 6/7: Checking and upgrading tables
Processing databases
epgrec
epgrec.rc_reserveTbl                               OK
(略 : データベースのテーブルを全部チェック
information_schema
performance_schema
wp_black
wp_black.wp1_commentmeta                           OK
(略 : データベースのテーブルを全部チェック
Phase 7/7: Running 'FLUSH PRIVILEGES'
OK
root@acid:~#

複数回の実行からは保護されてるっぽい

root@acid:~# mysql_upgrade -p
Enter password:
This installation of MySQL is already upgraded to 10.1.26-MariaDB, use --force if you still need to run mysql_upgrade
root@acid:~#

参考資料

https://dev.mysql.com/doc/refman/5.5/en/mysql-upgrade.html

https://mariadb.com/kb/en/library/mariadb-community-couldnt-execute-show-events-cannot-proceed-because-system/

今使ってるのMariaDBなのかMySQL(GPL)なのか、バージョンアップする前に調べたい。

apt で入れるのか、なにで入れてるのかわからなくなる。

docker のイメージだとか、mysql を含んだdeb とかあるから、ちゃんと確認した方がいいよね。

mysql takuya@localhost:(none)> select VERSION();
+--------------------------+
| VERSION()                |
|--------------------------|
| 10.1.26-MariaDB-0+deb9u1 |
+--------------------------+
1 row in set

参考資料

https://mariadb.com/kb/en/library/version/

マリアバージョン

bashでファイルを空にする。コマンド3種類

ファイルを空にしたい

フォルダやファイルの構造をそのままに、ファイルの中身を空っぽにしたい。

ファイルを消してtouch すれば良いんだろうけど、パーミッション設定しなおしたり面倒くさいよね。ファイルのinodeも変わってしまうので tail してたら tail し直しだ。ファイルをreadしてる常駐プロセスがあれば、そのでエラーになっちゃうし。

ファイルを空にする truncate

truncate -s0 path/to/file

これで、ファイルの中身を消せる。

truncate した場合の tail

tail してる場合は truncated と通知されるんですよ。

takuya@src$ tail -f src/index.html
aa
aa
tail: src/index.html: file truncated

ファイルを空にするリダイレクト

:>  /path/to/file

コマンドの : true と リダイレクト > を組合せて、ファイルをTruncateして空っぽにすることも出来る

echo で空文字 でもいい。

echo -n > /path/to/file

ddでマニアックに

もう一つの方法は dd でやるほうほう。これもマニアック。だけどちゃんとtruncateする。

要は ファイルをopen して先頭にカーソルを持ってきて何か書いてflush すれば良いわけです。

dd if=/dev/zero of=index.html bs=1 count=1

2018-02-26

追記修正

bashでファイルパスの相対パスを得る(絶対パスの取得やパスの正規化も)/realpath利用

realpath で解決

bashスクリプトで2つのファイルパス間の相対パスを取ろうとすると、計算が大変です。

LinuxMacもrealpath は入ってないので、 apt/brew でいれる必要があります。

realpath のインストール

macOS の場合はhomebrew で GNU Linux coreutils をいれる

brew install coreutils

coreutilsのインストールは好き嫌いが別れるのですが、私はGNUコマンドでいいからガンガン入れてしまってます。

絶対パスの取得

realpath ../../../.bashrc

相対パスの取得

realpath --relative-to=/Users/takuya/.ssh /

ちょっとわかりにくいけど、/Users/takuya/.sshからみた /相対パスが出力される。

. しか見えないときにわかりやすいかも

相対パスの取得の例

カレントディレクトリから、カレントディレクトリを見た場合

$ realpath --relative-to=.  .
.

下の階層を見た場合

/ から /tmp を見た場合

$ realpath -s --relative-to=/ /tmp/
tmp

基本的な相対パスの求めから

ディレクトリ Aからみたディレクトリ Bが欲しい時

$ realpath -s --relative-to=A B

ファイルA.txtからみたファイルB.txtへの相対パスが欲しい時

realpath --relative-to=$(dirname A.txt) B.txt

相対パスを求めるときは、 --relative-toディレクトリを入れるとわかる。

/var/www からみた /var/log

takuya@sites$ realpath --relative-to=/var/www /var/log
../log

/var/www/html からみた /var/log

$ realpath --relative-to=/var/www/html  /var/log
../../log

うん、この感じいいね。

/var/www/html/index.php からみた /var/log

んん????

$ realpath --relative-to=/var/www/html/index.php  /var/log
../../../log 

ああ、ファイル名をエントリとして1段の下の階層に来てしまうね。

ファイルをいれるときは dirname を使うよね。

$ realpath --relative-to=$(dirname /var/www/html/index.php)  /var/log
../../log 

持っててよかった realpath

realpath を入れておくと便利ですよね。

realpath コマンドがない場合

そういう時もありますよね。

python の os を使う。

import os.path, sys;
print os.path.relpath('A' ,'B')

ruby のpathnameを使う

require 'pathname'

path = Pathname.new("/tmp/foo")
base = Pathname.new("/tmp")

path.relative_path_from(base)

割となんとでもなるね。

curl で api に画像をアップロードするのに、base64をする。

application/json でファイルを送信する

curl でファイルアップロードをしようとしたら、Content-Typeを text/json で、本文にJSONで画像を入れろって言われたの。

echo {\"image\": \"$( base64 -w0 path_to_file )\" }  | \
curl -X POST -H "Content-Type: application/json" -d @-  http://localhost/api/photo

こうすれば、json を使っても画像を送信することが出来る。

APIでマルチパートを受け取って欲しい。

なんで、わざわざ base64 にして送らなきゃいけないんだろう。

HTTPはMultipart導入ででせっかくファイルアップロードを解決したのに、それを全部無視して、フレームワークが処理してるの。。。

車輪の再発明どころか劣化してると思った。バッカじゃないの??

pyenv でインストールされたpipを含めてupgradeする方法

pyenv の pythonバージョンアップしたい

pyenv でインストールしたpythonバージョンアップして、pipをmigrate したい・

pyenv はバージョン毎にpip環境が作られるから、pyenv でglobal をアップグレードすると、使ってたpipのパッケージが移動されずに真っ白な環境になってしまう。

そこで pipのパッケージをmigrationしたいと思った

pyenv-pip-migrate で一括アップグレード

pyenv-pip-migrate という モジュールがあって、コレを使えばマルっとバージョンアップしてくれることがわかった。

pyenv-pip-migrateのインストール

brew install pyenv-pip-migrate

これをインストールしたら準備完了

pyenv でバージョンアップする

現状が次のバージョンなので、これを3.6.4にする。

$ pyenv version
3.6.0 (set by /Users/takuya/.pyenv/version)

バージョンアップしよう

現状は 3.6.0 だったので、これをアップグレードしてpython の pip モジュールもアップグレードしていきます。

準備

brew install pyenv-pip-migrate

python の 最新版(2018-02-17現在)をいれる。

$ pyenv install 3.6.4
Installed Python-3.6.4 to /Users/takuya/.pyenv/versions/3.6.4

version 3.6.4 がインストールされました。

$ pyenv versions
  system
* 3.6.0 (set by /Users/takuya/.pyenv/version)
  3.6.4

pip を最新版バージョンに併せて置き換える。

python の一括が終わったら、pipを入れていきます。

今回は 3.6.0→3.6.4 にあげていきます。

$ pyenv migrate 3.6.0 3.6.4

これで、pip のインストールが始まる。

仕上げ

最後に仕上げです。新バージョンにglobalを変える

$ pyenv global 3.6.4

これで問題なく環境を移行できました。楽ちん!

せっかちな人向け

OLD_VERSION=$(pyenv version global version | sed 's/\s.*$//')
NEW_VERSION=$(pyenv install --list  | \sed "s/\s*//"  | \grep -P '^\d\.\d\.\d$' | \sort -nr | \head -n 1)
brew install pyenv-pip-migrate
pyenv install $NEW_VERSION
pyenv migrate $OLD_VERSION $NEW_VERSION
pyenv global $NEW_VERSION

エラーになったり、移行させるパッケージを選びたいよって人向け

現在のpipの状態は freeze で持っていけるので、それを使うといい

pip freeze > requirements.txt

つまり、古いバージョンの方で freeze して 新しいバージョンで install する。

pyenv global 3.6.7
pip freeze > requirements.txt
## 適当に編集
vim requirements.txt
## バージョンを切り替え
pip global 3.7.0
pip install -r requirements.txt

わざわざ、migration 入れないでいいのは便利。

参考資料

https://github.com/pyenv/pyenv-pip-migrate