それマグで!

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

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

Chromeの開発ツールのネットワークから拡張機能のログを隠す

Google Chrome の開発ツールに拡張機能が邪魔

プライベート・ブラウズ・モードでアクセスすれば、拡張機能のリクエストログをを隠すことが出来るが。

わざわざ拡張機能のためにプライベートブラウズで悪世するのも面倒ですよね。

ネットワークのフィルタを使う

そこで、devtool -> network -> filter にある、フィルタを使う方法があった。

-scheme:chrome-extension

これで拡張機能のログを隠せる。

f:id:takuya_1st:20190913144252p:plain

ちなみに、以下が拡張機能のネットワークのログを隠す前です。 f:id:takuya_1st:20190913144646p:plain

見比べてみたら減っているのがわかるでしょうか。

便利!!

拡張機能の通信ログが出てくるのを隠せないのか?

たぶん無理です。 chrome-extension のログを隠すのは、セキュリティ上の問題だと思う。

参考資料

https://stackoverflow.com/questions/16436369/is-it-possible-to-hide-extension-resources-in-the-chrome-web-inspector-network-t

Mac でVPNを接続するコマンド。ついでに整理しておく

macVPNを接続する。

Macに標準のサービスを使って設定しているPPP系 LT2P over TLS のような設定だとnetworksetup から出来る

scutil もいいけど、networksetup でもいい。私はこっち。

macVPNに接続するには

networksetup -connectpppoeservice "$VPN_NAME"

切断するには、

networksetup -disconnectpppoeservice "$VPN_NAME"

接続状態を見るには。

networksetup -showpppoestatus "$VPN_NAME"

$VPN_NAME :サービス名を取得するには

覚えられないので、bashrcにした

networksetup はコマンドが多過ぎて、覚えられないで、bashrcに書くことにした。

#!/usr/bin/env bash



if ! [[ $plat_name =~ darwin ]] ; then
    return;
fi


function vpn.getFullName(){
  VPN_NAME=$(networksetup -listallnetworkservices  | \grep $1  );
  echo $VPN_NAME;
}

function vpn.isConnected(){
  VPN_NAME=$( vpn.getFullName $1 )
  [[ $(networksetup -showpppoestatus "$VPN_NAME" )  == connected ]];
}
function vpn.disconnect {
    vpn.menu_icon.conceal
    VPN_NAME=$( vpn.getFullName $1 )
    networksetup -disconnectpppoeservice "$VPN_NAME"
}
function vpn.menu_icon.conceal() {
    if type vpn_menu.py  2>&1 > /dev/null ;then
        vpn_menu.py -d
    fi
}
function vpn.menu_icon.display() {
    if type vpn_menu.py  2>&1 > /dev/null ;then
        vpn_menu.py -e
    fi
}

function vpn.connect(){
    vpn.menu_icon.display
    VPN_NAME=$( vpn.getFullName $1 )
    vpn.disconnect "$VPN_NAME"
    vpn.isConnected  "$VPN_NAME" || networksetup -connectpppoeservice "$VPN_NAME"
    cnt=0
    echo "conncting...";
    while ! vpn.isConnected "$VPN_NAME"
    do
    (( cnt++ ))
    printf "${cnt} time  .waiting...\r"
    sleep 1
    if (( $cnt > 30 )) ; then
      echo failed.
      return 1 ;
    fi
    done;
    printf "                                  \r"
    echo "connected"
    return 0;
}

function vpn.addRoute(){
  echo add route;
  for IP_ADDR; do
    echo ip route add ${IP_ADDR}/32 dev ppp0
    ip route add ${IP_ADDR}/32 dev ppp0
  done

}

関連資料

sudo -e ( sudoedit ) でvimで保存しても反映されない

sudo -e (名前=sudoedit ) コマンドは一時ファイルで編集する

sudo -e とは環境変数EDITORを使って、/tmp フォルダにファイルを作ってそれを開いてくれる。 エディタのプロセスを終了したら、元のファイルに上書きされる

:w だけでは反映されない

vim で開いているときは、 :w だと反映さません。時々ハマります、 :w を押しても更新が結果に出ない。 sudo -e を使っていると、なんでなんで、とパニックになることがあります。

sudoedit / sudo -e はそういうものです。

man sudo を見てみると sudoedit のポイントは次の通り。

長いので抜粋

シンボリックリンクの編集は許可しない

セキュリティポリシーによって指定されたエディタを起動して、 テンポラリファイルを編集する。

編集対象のファイルのコピーをテンポラリファイルとして作成する。 
編集作業がすむと、テンポラリファイルをオリジナルのファイルにコピーして、 テンポラリファイルを消去する。 


sudoers ポリシーでは、環境変数 SUDO_EDITOR,VISUAL, EDITOR を (この順番で) 使用する。
-e でエディタが実行されるときは、sudo を起動したユーザの環境が、 変更を受けずに使われる。

:w で保存できないのはそういうものです

sudo -e は不意な変更や途中でいったん保存したときに影響が出来ないよう

環境変数の維持が目的なら

vim の設定をそのまま引き継ぎたいなら、次のような代替手段がある。

sudo -E vim 
sudo -E $EDITOR

個人的な感想ですが

sudo vim するよりも、記述途中でファイルをいったん保存できるので、sudo -e のほうが好きです。

でも、終了しないと反映しないのをわすれてよくトラブります、その点については諦める。

参考資料

man sudoedit

-e, --edit 何らかのコマンドを実行するのではなく、1 個以上のファイルを編集する。 セキュ リティポリシーの参照では、コマンドのパス名の代わりに "sudoedit" という文字列 が使用される。 セキュリティポリシーによってユーザに権限があることが認められ ると、 次のことが順番に行われる。

             1.   編集対象のファイルのコピーをテンポラリファイルとして作成する。 テン
                  ポラリファイルのオーナーは sudo を起動したユーザである。

             2.   セキュリティポリシーによって指定されたエディタを起動して、 テンポラ
                  リファイルを編集する。sudoers ポリシーでは、環境変数 SUDO_EDITOR,
                  VISUAL, EDITOR を (この順番で) 使用する。 SUDO_EDITOR, VISUAL,
                  EDITOR のどれも設定されていない場合は、 sudoers(5) の editor オプ
                  ションにリストされたプログラムのうち、 最初のものが使われる。

             3.   編集作業がすむと、テンポラリファイルをオリジナルのファイルにコピー
                  して、 テンポラリファイルを消去する。

         編集する権限のないファイルを編集できないようにするため、 セキュリティポリ
         シーによって明示的に許可されていないかぎり、 以下の制限が行われる。

                         ·   シンボリックリンクの編集は許可しない (バージョン 1.8.15
                             以上)。

                         ·   sudo を実行するのが root であるときを除いて、 編集する
                             ファイルのパス中にシンボリックリンクがある場合、 そのリ
                             ンクの親ディレクトリが sudo を実行するユーザにとって書き
                             込み可能ならば、 リンクをたどらない (バージョン 1.8.16
                             以上)。

                         ·   sudo を実行するのが root であるときを除いて、 ファイルが
                             sudo を実行するユーザにとって書き込み可能なディレクトリ
                             にある場合、 そのファイルの編集を許可しない (バージョン
                             1.8.16 以上)。

         ユーザがデバイス・スペシャルファイルの編集を許可されることは絶対にない。

         指定されたファイルが存在しない場合は作成する。ここで注意すべきは、 sudo に
         よって実行されるコマンドの大部分と違って、 -e でエディタが実行されるとき
         は、sudo を起動したユーザの環境が、 変更を受けずに使われるということだ。 何
         らかの理由で sudo が編集した内容でファイルを更新できないときは、 ユーザに警
         告を発し、編集した内容をテンポラリファイルに保存することになる。

xvfb-run が標準エラーと標準出力を併せてしまう件

xvfb-run で実行すると stderr が取れない。

/usr/bin/xvfb-run を使えば楽ができる。 Xvfb を起動してDISPLAY変数をセットして、DISPLAY変数を渡して別途起動する、というプロセス管理をぱぱっとやってくれるシェルスクリプトです。

しかしstderr が取れない。

実行時に、このようにしてもstderr を捨てることが出来ない。

/usr/bin/xvfb-run /usr/bin/node chrome-cdp-sample.js 2>/dev/null

/usr/bin/xvfb-run が 2>&1 してた。

/usr/bin/xvfb-run:180行付近で渡されたコマンドをXvfb経由で実行されているのですが

# Start the command and save its exit status.
set +e
DISPLAY=:$SERVERNUM XAUTHORITY=$AUTHFILE "$@" 2>&1
RETVAL=$?
set -e

なんと、2>&1 してます。まじかよ。

これを、こう

# Start the command and save its exit status.
set +e
DISPLAY=:$SERVERNUM XAUTHORITY=$AUTHFILE "$@"
#DISPLAY=:$SERVERNUM XAUTHORITY=$AUTHFILE "$@" 2>&1
RETVAL=$?
set -e

こうすれば、stderr を取れますね。 なんでこんな事になってるんだろう。意味があるんだろうけど、想像がつかない。

参考資料

phpでOSの判定をする組み込み変数

php で実行環境をチェックするには

PHP_OS という、ウルトラ素晴らしい定数が、最初から組み込まれています。

<?php
var_dump(PHP_OS);

実行結果

macOS ( OS X ) での実行結果

string(6) "Darwin"

Ubuntu での実行結果

string(5) "Linux"

とてもかんたんにOSを判別できます。

参考

https://www.php.net/manual/en/reserved.constants.php

Excelの書式設定で数字を0埋めする。(ゼロパディング)

Excel で数字をゼロ埋めたい。

000123 のように数字を0で埋めることで、桁数が揃ったり、視認性があるので採用する人も多いと思います。

また、最大桁数が一瞥してわかるのも魅力ですね。

ゼロ埋めはヒューマンインタフェース*1として、対人間との情報のやり取りとして非常に優秀です。

数字をゼロ埋めにする書式設定

次のような、セルがあるときに

f:id:takuya_1st:20190909142609p:plain ( A列は比較用です

セルの書式設定→その他

セルの書式設定を呼び出します。

f:id:takuya_1st:20190909142621p:plain

書式設定で0をたくさん書きます。

ゼロの数でゼロ埋めの個数が決まります。

 0000: 123→ 0123
00000: 123→00123

今回は、0 を6つ書きました。

f:id:takuya_1st:20190909142636p:plain

000 の場合です。

では、最大桁数より少ないゼロの数を指定したらどうなるでしょうか。

結果は次のようになります。 f:id:takuya_1st:20190909144642p:plain

二回目以降はユーザー定義

一度書式を指定したら、次から、ユーザー定義に出現します。

そこから選ぶのが速いでしょう。

ユーザー定義書式に名前をつけられたいいのにな。

数字?文字?

数字のゼロ埋め 00123 のように記載するのは、文字列と数値をごっちゃにするので、あまりよろしくないのですが。

何がよろしくいかというと、数字であるところを、文字列にしてしまう方がいらっしゃいます。

さら悪いことには、ごっちゃにする方々への予防策のために、担当者が「うちでは0埋めを採用しない」とか「0埋めをみたら文字列だと思え」などと、謎なローカル・ルールが誕生してたりします。
声の大きいひとの意見が通るのは良くないですよね。理性的に行動してほしい。

セルの値を「数字」としてあつかい、表示の書式設定で0を補って数字を書式表示するのが正しい。

Excel ワールド

プログラミングを習ったことがある人だと printf(%06d, 134 ) のような printf による書式を考えてしまいがちです。

しかし、ExcelVBAには GNU bash のような 組み込み printf も、C言語のような stdio による printf もありません。

Excelにはエクセルの流儀があり、プログラミングの世界にはプログラミングの流儀があがります。

私はプログラマなので、これをExcel異世界だと思うようにしています。プログラミングとExcelの世界は似ていますが、違いますね。

「郷に入れば郷に従え」の通り、あれこれローカルルールや独自基準をつくらず、素直な解決方法を受け入れるようにしたいです。

*1:今どきの呼び方をするなら、UI/UXでしょうか

Excel でセルの書式設定をすると、なぜか中国(台湾・イ語)にロケールがなってしまう。

excelの書式設定を変えると。。。

なぜか、セルの書式設定で 0000 を設定し、再度画面を開くと、書式設定が次のように、非日本語判定されてしまいました。

f:id:takuya_1st:20190909135810p:plain

私は台湾はスキなんだけど、いまこのExcelで台湾を求めてないんです。

なぜか中国判定されてしまう。

別に問題はないのだけれど、ちょっと気持ち悪いと思います。

解決策

[$-ja-JP]0000000

設定したところ f:id:takuya_1st:20190909135835p:plain

これで解決。する。

嘘だろと思ったけど、本当に解決したので、メモ。

参考資料

Excelの「セルの書式設定」の「ユーザー設定」における先頭に0がある数値の設定につ - マイクロソフト コミュニティ

PostgreSQLにあとからUNIQUE制約を追加する。

PostgreSQL

PostgreSQLにあとからUNIQUE制約を追加する。

ALTER TABLE "TABLE_NAME" add constraint "your_name_of_constraint_key"  uniq ("COLUNM_NAMES");

PostgreSQL にあとからUNIQUEを削除する

ALTER TABLE "TABLE_NAME" drop constraint "your_name_of_constraint_key"  uniq ("COLUNM_NAMES");

参考資料

http://taramonera.hatenadiary.jp/entry/20101014/1287032499

dockerがapt失敗する - dns の設定を見直してみる。

Docker で起動したUbuntuがネットに出られない。

docker コンテナ側からインターネットへのネットワークの疎通を確認する。

今回は、なぜか、通信ができなかったので、エラーになる。いきなり発生したので原因を探っておく。

疎通確認

docker run busybox ping -c 1 8.8.8.8

これは、docker のコンテナを起動してpingを起動して実行する。

こんどは、docker コンテナからインターネットへのDNS名前解決を確認する

名前確認。

任意のドメインに、pingを打って名前解決を確認する。

takuya@:docker run busybox ping -c 1 t.co

今回は、ここでエラーになっていた。

DNS名前解決が出来ないときは、docker コンテナの nameserver 設定を確認する。

takuya@:~$ docker run busybox cat /etc/resolv.conf
nameserver 192.168.11.111

あ・・・ホストのDNS設定そのままコピーされてるやん

docker のネームサーバー設定は、ホストから

そうなんですね、Dockerのネームサーバーの設定は、ホストからコピーされることがあります。

DNS の設定は、docker ホスト側のresolv.confに従うが、私のサーバーのresolve.conf は localhost の unbound を見に行く。

そのため、ホスト側のDNSと同じ設定が適用されるのだが、これが必ずしも使えるとは限らない。

例えば、私はunbound側でresolveを許可するネットワークを絞っている。

takuya@:bwdata$ ip addr show  docker0
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:58:e2:8b:63 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:58ff:fee2:8b63/64 scope link
       valid_lft forever preferred_lft forever

私の場合、次のようなdocker0 ネットワークインターフェースが存在するので、このIPレンジからの問い合わせに答えてあげなくていはいけない。

access-control: 172.17.0.1/16 allow_snoop  ## docker network

今回は、私のホスト側に設定している dns サーバーがIPアドレス制限を行ってたのでapt に失敗してた。

Docker で名前解決が失敗するときは

takuya@:~$ docker run --dns=8.8.8.8   busybox  cat /etc/resolv.conf
nameserver 8.8.8.8

DNSはまとめて設定ファイルに書くことができる。

dokcer のホスト側にdocker のオプションを書きところがあり、そこの記述を追記してあげれば固定できる。

takuya@:~$ sudo cat /etc/docker/daemon.json

{
        "dns": ["8.8.8.8"]
}

上記の方法を試すなど、として様子を見てみるのもいいだろう。

docker のDNSは8.8.8.8になる

ホスト側のdns 設定がlocalhost の場合

takuya@:~$ cat /etc/resolv.conf
nameser 127.0.0.1

ホスト側がlocalhostを参照しているので、docker コンテナにこのままコピーされると詰む、なので、

takuya@:~$ docker run busybox cat /etc/resolv.conf
nameser 8.8.8.8

この場合、127.0.0.1をコピーすると詰むので、docker のコンテナには、8.8.8.8 が自動で設定されるのかもしれない。

参考資料

Configure container DNS | Docker Documentation

macOSのメニューバー項目を コマンドから表示・非表示をトグルして切り替える。(VPNの表示非表示の例

macのメニューバーの項目を表示・非表示するのがメンドクサ

VPN を接続したときだけメニューバーに表示してくれればいいのに、VPNを使わないときもVPNメニューがでてくるのは邪魔だよね。

defaults で制御できる。

メニューバーの項目は、defaults で設定値を取り出せるんです。

takuya@menubar$ defaults read com.apple.systemuiserver menuExtras
(
    "/System/Library/CoreServices/Menu Extras/Clock.menu",
    "/System/Library/CoreServices/Menu Extras/Battery.menu",
    "/System/Library/CoreServices/Menu Extras/TextInput.menu",
    "/System/Library/CoreServices/Menu Extras/User.menu",
    "/System/Library/CoreServices/Menu Extras/TimeMachine.menu",
    "/System/Library/CoreServices/Menu Extras/AirPort.menu",
    "/System/Library/CoreServices/Menu Extras/Volume.menu",
    "/System/Library/CoreServices/Menu Extras/Bluetooth.menu"
)

これを使えば、書き込むことも可能でしょ。欲しい物だけ、トグル出来たら便利なので。

VPNメニューのボタンアイコンって、ダサいんですよ。

f:id:takuya_1st:20190903175429p:plain

f:id:takuya_1st:20190903175444p:plain

VPNメニューをトグルするサンプル

特に工夫もなく、思いつくままに書き加えたコードがこちら。

import ast
import subprocess
import argparse
from pprint import  pprint as pp



def toggle_vpn_menu( enable=True ):
  vpn_menu = '/System/Library/CoreServices/Menu Extras/VPN.menu'

  ret = subprocess.check_output("defaults read com.apple.systemuiserver menuExtras", shell=True, universal_newlines=True)
  menus = ast.literal_eval(ret)

  vpn_menu_exists = any([vpn_menu in e for e in menus])

  if vpn_menu_exists  and enable is False : # disable
    ##
    menus = [x for x in menus if not vpn_menu in x]
    cmd = 'defaults write com.apple.systemuiserver menuExtras -array '.split() + menus
    subprocess.check_call(cmd)
    ##
    cmd = "killall SystemUIServer -HUP".split()
    subprocess.check_call(cmd)
    return

  if not vpn_menu_exists and  enable is True: # enable
    menus = list(menus)
    menus.append(vpn_menu)
    cmd = 'defaults write com.apple.systemuiserver menuExtras -array '.split() + menus
    subprocess.check_call(cmd)
    ##
    cmd = "killall SystemUIServer -HUP".split()
    subprocess.check_call(cmd)


def main():
  parser = argparse.ArgumentParser(description=u'VPNメニューをオンオフする。')

  parser.add_argument('-e ', '--enable', action="store_true", help=u'有効化')
  parser.add_argument('-d ', '--disable', action="store_true", help=u'無効化')

  args = parser.parse_args()

  if args.enable:
    toggle_vpn_menu(True)
  else:
    toggle_vpn_menu(False)



if __name__ == '__main__':
    main()

ちなみに、表示するだけなら

` '/System/Library/CoreServices/Menu Extras' `` にある該当メニューをダブルクリックして開くだけで、表示だけならできる。

"open '/System/Library/CoreServices/Menu Extras/VPN.menu'"

f:id:takuya_1st:20190904110543p:plain

nginx で 443 default_server を入れたら接続できなくなる

443 で default_server を入れたら通信がおかしくなる件

nginx でドメインをキャッチオールして、別サーバーのnginx へ丸投げする、多段nginx の設定を書いていたら、80 だと動くんだけど、443 で動かない。

listen 443 ssl https default_server

をつけると動かなくなる件

Chrome で接続すると、次のようになる。

SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET

原因がわからず結構苦労した。

SNI かと思ったけど、どうも違う。SSLのセッションチケットが変わってしまうようです。

これは動くんですが、

listen 80   http default_server
listen 8080 http default_server

ssl をつけると動かない。

listen 443  ssl http2 default_server
listen 8443 ssl  http2 default_server

Errors from browsers with ssl_session_tickets off (nginx)

nginx の メインの設定( server { } 外)に 次の設定を書いて、既存のSSLのセッションを無視するようにする。

ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;

たぶんだけど

SSLのセッションはChromeが管理していて、以前の接続と違うSSLが開始したら、MITMとか?エラー検出してるんだと思う。

そういえば、default_server と server で使ってる証明書は別でした。

参考資料

https://community.letsencrypt.org/t/errors-from-browsers-with-ssl-session-tickets-off-nginx/18124/5

iOSのショートカット.app のファイルを取り出す方法。

iOS のショートカットのアプリで作成したものは取り出せます。

ファイルとして取り出せるんです。

f:id:takuya_1st:20190901120648p:plain:w250

保存するメリット

ショートカットをファイルとして保存することができ、中身を閲覧することが出来ます。中身は plist です。plitul などで中身編集することも出来ます。

テキストファイルにしておけば、git でバージョン管理に突っ込めるし、

Javascriptについては、MacやPCでぱぱっと編集ができるぞ

手順

ショートカットをファイルとして保存する歩法。

1. 該当するショートカットを開いて

コレクションから、保存したいショートカットを開きます。

f:id:takuya_1st:20190901120535p:plain:w200

2. ファイルに保存を選ぶ。

f:id:takuya_1st:20190901120549p:plain:w200

3. 保存先を選ぶ

保存先には iOS Files に対応したアプリや NextCloud、EvernoteGoogle Drive など、

手っ取り早いのは、AirDropで作成されたファイルをMacに送ること。

f:id:takuya_1st:20190901120555p:plain:w200

あれ、これできるってことは、bookmarkletiOSショートカット変換が、すぐできるんじゃ。

s3互換 minio を使って AmazonS3 の実験コストを節約する

minio はバージョンアップして使い方が変わった

次を参照のこと。

s3互換ストレージminio をインストール(2021版) - それマグで!

Aws の S3 の代替サーバーを使う。

s3 の設定をいちいちするのはめんどくさいので、使い捨ての s3 が欲しくなる。

minio オブジェクトストレージ

minio というS3と同様のオブジェクトストレージが使えるサーバを使って、開発コスト(時間設定金銭)を下げてしまえ。

Docker で手軽に起動する

MASTER_KEY=$( cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1 ):$(openssl rand -hex 32)
docker run -it -e MINIO_SSE_MASTER_KEY=$MASTER_KEY restart=always -p 127.0.0.1:4569:9000  minio/minio server /data

ちなみに 4569 は fakes3 と合わせてある。

docker-compose に含めて、オブジェクトストレージ使い捨てのエミュレーションならdockerで十分

ローカルにオレオレS3としてサービスするんだったら。

オブジェクトストレージを自分で運営しようとすると、docker でもいいけど、フロント側でサーバー起動したほうが楽かもしれない。

サーバーのバイナリをとってきて、起動するのがいい。

/usr/bin/curl -LJO https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x ./minio
MASTER_KEY=$( cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1 ):$(openssl rand -hex 32)
export  MINIO_SSE_MASTER_KEY=$MASTER_KEY
./minio server /var/www/virtualhosts/path/storage --address  127.0.0.1:4569

こうしておけば、サービスとして動かせるので、S3の代わりにデータをどんどん放り込んでいける。

ただしmino にs3の完璧は互換性は無いし、ファイルのバージョニングなどの機能はないから注意が必要。

起動したら、次のような画面になる。

ここで AccessKey と Secret Keyを取得しておく

f:id:takuya_1st:20190829165317p:plain

ブラウザで( 今回は 127.0.0.1:4569:9000) にアクセスすると、なんとWebUIが使える。

これは評価高い。

f:id:takuya_1st:20190829165254p:plain

nginx でプロキシして、公開サーバとして使ってもいいと思う。

systemd でサービス化してみる。

systemd 起動する minio.service

[Unit]
Description=minio サーバーのインスタンス


[Service]
WorkingDirectory=/var/www/minio
ExecStartPre=/bin/bash update-minio.sh
ExecStart=/var/www/minio/minio server /var/www/minio/storage --address  127.0.0.1:4569


## 定期的に再起動して最新版を取得する
Restart=always
RuntimeMaxSec=864000

[Install]
WantedBy=network-online.target

systemd で起動しておく

sudo systemctl daemon-reload
sudo systemctl start minio
sudo systemctl status minio

サーバーバイナリの更新をどうするか

systemdで起動しても、もともとがwget で取得したバイナリなので、定期的にアップデートする必要がある。 apt で更新できる *.debが公開されてればよかったんだけどね。提供されてないようなので、自分で更新チェックをすることにした。どうせ1ファイルだし。

定期的に再起動しつつ、定期的にminio のサーバーバイナリを取得する

#!/usr/bin/env bash


cd  /var/www/minio


server_shas=$(curl -s https://dl.min.io/server/minio/release/linux-amd64/minio.shasum | cut -d' ' -f 1  )
local_sha=$( sha1sum minio | cut -d' ' -f 1  )


if [[  ! -e minio ]] ||
  [[ $server_shas != $local_sha ]] ||
  (( $(( $(date +%s) - $(date -r minio +%s)  )) > $(( 60*60*24*30 ))  )); then
  /usr/bin/curl -LJO https://dl.min.io/server/minio/release/linux-amd64/minio
  chmod +x ./minio
fi

s3cmd からの動作チェック

s3 互換ということなので、s3cmd のような s3 管理ツールからオブジェクトストレージとして使ってみる。

brew install s3cmd

~/.config/minio

設定ファイルを作っておく

[default]
host_base = 127.0.0.1:4569
host_bucket = 127.0.0.1:4569/%(bucket)s
bucket_location = us-east-1
use_https = True

access_key = HEDXXXXXXXXXXXXXXXXXXXXX
secret_key = cenXXXXXXXXX+XXXXXXXXXIkKe7LrqA

signature_v2 = True

minio を s3cmd で試してみます。

バケットの作成 mb:make bucket する。

takuya@.config$ s3cmd -c ~/.config/minio  mb    s3://sample
Bucket 's3://sample/' created

ファイルをアップロードする

takuya@.config$ s3cmd -c ~/.config/minio put -r /Users/takuya/Pictures/EAWBB3YUEAEmkOl-1.jpg  s3://sample
upload: '/Users/takuya/Pictures/EAWBB3YUEAEmkOl-1.jpg' -> 's3://sample/EAWBB3YUEAEmkOl-1.jpg'  [1 of 1]
 53125 of 53125   100% in    0s   388.63 kB/s  done

バケットの中身を確認する。

takuya@~$ s3cmd -c ~/.config/minio ls   s3://sample
2019-08-29 03:27     53125   s3://sample/EAWBB3YUEAEmkOl-1.jpg

バケットの閲覧

サイトにURLとして埋め込んで、アクセスキーなしにバケットを閲覧(HTTP/GET)しようとするには、管理画面でバケットのポリシーを設定するか,
公開ポリシーをs3cmd などで設定する必要がある。

まとめ

minio でAWS S3 にいちいちクレジットカードを登録しなくても、Amazon S3を使ったサーバーアプリケーションを使ったり、開発ができる。
クレジットカードの登録を経理通すとかめんどくさいし、ぱぱっと試せてるのは強いと思う。

今回は、試すというより、S3なくてminioでもういいじゃんってこと思ったので、S3をエミュレーションして永続ストレージとして使うような感じにした。

バージョニングとかgracier のようなバックアップなどは使えないが、分散ストレージは出来たりするので結構面白いソフトウェアなんじゃないかな

開発中のモックアップとしてはminioは大きすぎるのでfakes3のほうがいいかなと思った

参考資料

ファイルが作成されてから何秒経っているか?作成後指定秒経過したらなにかする。

ファイルが作成されてから何秒経っているか?

このファイルが、作成されてから何秒経過したか。それ知りたいことありませんか?

ファイルAがファイルBより古いときはファイルAを更新するとか

作成後(更新後)の経過秒数を知る

echo $(( $(date +%s) - $(date -r FILE +%s)  ))

これだけです。かんたんですね

コマンドの、細かいところを一つずつ見ていきます。

date コマンドでint秒数を表示する

まずは date コマンドで秒数を出す方法。これは現在のunix 秒が出ます。

date +%s

date コマンドでファイルの更新日付を取得する

次に、ファイルの更新時刻を date の引数として指定してあげる。

date -r FILE

組み合わせて、date コマンドでファイルの作成時をint秒で表示する

date -r FILE +%s

Bashで引き算をする

unix 秒が取れる なら、これを比較のために引き算して上げる必要があります。

echo $(( 100 -1 ))

これらをすべて組み合わせる

ファイルが作られてから何秒(何時間)経過しているかが計算できる

echo $(( $(date +%s) - $(date -r FILE +%s)  ))

条件判断に使う。

ファイルが作成されてから1000秒経過してたら再起動するような条件分岐に使うことが出来ます。

(( $(( $(date +%s) - $(date -r FILE +%s)  )) >  1000 ))  && restart-server

ファイルA/BでAのほうが古ければなにかする。

(( $(( $(date +%s -r FILEA ) - $(date -r FILEB +%s)  )) <  0 ))  && echo old

記号 $( ( expr )) や ( ( expr )) などのbash の記号については

Bashの記号については、過去記事を参考にしてください

参考資料

man bash

nginx で proxy 時に header を除去する-CSP上書き削除書き換え

nginx で http header を上書き除去する。

nginx でアプリケーションへ reverse proxy してたんだけど、アプリケーション側にcontent-security-policy の設定が最新版のChromeと合わなかった。とくに blog/data

add_header で csp を追記しようとしたけど、セキュリティは全部OKから絞っていくほうが設定が楽。

なので、一旦全部許可しようと思ったんだけど、あれ除去ってどうやるんだよ。と気づいて調べたのでメモ

これでは、上書きにならない。あくまでついか

add_header  content-security-policy '';

nginx で http header を消すー削除

そこで、アプリケーションからのレスポンス中のヘッダを除去して応答を再生成することにした。

proxy_hide_header  "content-security-policy";

これで、ブラウザに返すレスポンスから特定のヘッダを削除して見えなくすることができる。

ちなみに、proxy_set_header で空文字を与えても同じようなことはできるけど

proxy_set_header cache-control ''

こちらは空文字を送信するので完全に消えるわけじゃない。

ちなみに、proxy_ignore_headersと似たような名前の設定が他にもあるが、これは proxy - proxy 間で使われるヘッダ( X-REAL-IP のような ) を除去するものらしい。

いったん削除して追加する。(上書き)

上書きならセットをつかう。追加なら

proxy_set_header cache-control 'default ...'
add_header cache-control 'image ...'

まとめ

ヘッダの追加・削除、上書き(削除追加)でそれぞれちょっと工夫が必要

関連資料

Module ngx_http_proxy_module