excelの書式設定を変えると。。。
なぜか、セルの書式設定で 0000 を設定し、再度画面を開くと、書式設定が次のように、非日本語判定されてしまいました。
私は台湾はスキなんだけど、いまこのExcelで台湾を求めてないんです。
なぜか中国判定されてしまう。
別に問題はないのだけれど、ちょっと気持ち悪いと思います。
解決策
[$-ja-JP]0000000
設定したところ
これで解決。する。
嘘だろと思ったけど、本当に解決したので、メモ。
ALTER TABLE "TABLE_NAME" add constraint "your_name_of_constraint_key" uniq ("COLUNM_NAMES");
ALTER TABLE "TABLE_NAME" drop constraint "your_name_of_constraint_key" uniq ("COLUNM_NAMES");
docker コンテナ側からインターネットへのネットワークの疎通を確認する。
今回は、なぜか、通信ができなかったので、エラーになる。いきなり発生したので原因を探っておく。
docker run busybox ping -c 1 8.8.8.8
これは、docker のコンテナを起動してpingを起動して実行する。
こんどは、docker コンテナからインターネットへのDNS名前解決を確認する
takuya@:docker run busybox ping -c 1 t.co
今回は、ここでエラーになっていた。
takuya@:~$ docker run busybox cat /etc/resolv.conf nameserver 192.168.11.111
あ・・・ホストのDNS設定そのままコピーされてるやん
そうなんですね、Dockerのネームサーバーの設定は、ホストからコピーされることがあります。
DNS の設定は、docker ホスト側のresolv.confに従うが、私のサーバーのresolve.conf は localhost の unbound を見に行く。
そのため、ホスト側のDNSと同じ設定が適用されるのだが、これが必ずしも使えるとは限らない。
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 に失敗してた。
takuya@:~$ docker run --dns=8.8.8.8 busybox cat /etc/resolv.conf nameserver 8.8.8.8
dokcer のホスト側にdocker のオプションを書きところがあり、そこの記述を追記してあげれば固定できる。
takuya@:~$ sudo cat /etc/docker/daemon.json { "dns": ["8.8.8.8"] }
上記の方法を試すなど、として様子を見てみるのもいいだろう。
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 が自動で設定されるのかもしれない。
VPN を接続したときだけメニューバーに表示してくれればいいのに、VPNを使わないときもVPNメニューがでてくるのは邪魔だよね。
メニューバーの項目は、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メニューのボタンアイコンって、ダサいんですよ。
特に工夫もなく、思いつくままに書き加えたコードがこちら。
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'"
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
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
ファイルとして取り出せるんです。
ショートカットをファイルとして保存することができ、中身を閲覧することが出来ます。中身は plist です。plitul などで中身編集することも出来ます。
テキストファイルにしておけば、git でバージョン管理に突っ込めるし、
Javascriptについては、MacやPCでぱぱっと編集ができるぞ
ショートカットをファイルとして保存する歩法。
コレクションから、保存したいショートカットを開きます。
保存先には iOS Files に対応したアプリや NextCloud、Evernoteや Google Drive など、
手っ取り早いのは、AirDropで作成されたファイルをMacに送ること。
あれ、これできるってことは、bookmarklet を iOSショートカット変換が、すぐできるんじゃ。
次を参照のこと。
s3互換ストレージminio をインストール(2021版) - それマグで!
s3 の設定をいちいちするのはめんどくさいので、使い捨ての s3 が欲しくなる。
minio というS3と同様のオブジェクトストレージが使えるサーバを使って、開発コスト(時間設定金銭)を下げてしまえ。
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で十分
オブジェクトストレージを自分で運営しようとすると、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を取得しておく
ブラウザで( 今回は 127.0.0.1:4569:9000) にアクセスすると、なんとWebUIが使える。
これは評価高い。
nginx でプロキシして、公開サーバとして使ってもいいと思う。
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
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
s3 互換ということなので、s3cmd のような s3 管理ツールからオブジェクトストレージとして使ってみる。
brew install s3cmd
設定ファイルを作っておく
[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
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 コマンドで秒数を出す方法。これは現在のunix 秒が出ます。
date +%s
次に、ファイルの更新時刻を date の引数として指定してあげる。
date -r FILE
date -r FILE +%s
unix 秒が取れる なら、これを比較のために引き算して上げる必要があります。
echo $(( 100 -1 ))
ファイルが作られてから何秒(何時間)経過しているかが計算できる
echo $(( $(date +%s) - $(date -r FILE +%s) ))
ファイルが作成されてから1000秒経過してたら再起動するような条件分岐に使うことが出来ます。
(( $(( $(date +%s) - $(date -r FILE +%s) )) > 1000 )) && restart-server
(( $(( $(date +%s -r FILEA ) - $(date -r FILEB +%s) )) < 0 )) && echo old
Bashの記号については、過去記事を参考にしてください
man bash
nginx でアプリケーションへ reverse proxy してたんだけど、アプリケーション側にcontent-security-policy の設定が最新版のChromeと合わなかった。とくに blog/data
add_header で csp を追記しようとしたけど、セキュリティは全部OKから絞っていくほうが設定が楽。
なので、一旦全部許可しようと思ったんだけど、あれ除去ってどうやるんだよ。と気づいて調べたのでメモ
これでは、上書きにならない。あくまでついか
add_header content-security-policy '';
そこで、アプリケーションからのレスポンス中のヘッダを除去して応答を再生成することにした。
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 ...'
ヘッダの追加・削除、上書き(削除追加)でそれぞれちょっと工夫が必要
引数 -d に @11234567 をつけます。
takuya@~$ date -d @1566808184 +"%F %T" 2019-08-26 17:29:44
date コマンドはミリ秒を解釈しないので、いったんint へ数値計算してやる
takuya@~$ date -d @$((1566808184122/1000)) +"%F %T" 2019-08-26 17:29:44
数値計算の方法は、過去記事にあるので、そっちへ
bashの似てて紛らわしいもの (( / $(( - それマグで!
date コマンドでフォーマットの方法は、過去記事があるので。参照
dateコマンドでiso/rfc日付時刻タイムゾーンをぱぱっとフォーマットして作る - それマグで!
npm でインストールしたパッケージはどうも使い捨ての傾向があり、アップデートを継続するにはちょっと手間が必要で。
npm のサブコマンドを使えばできる
npm update npm outdated
これらのコマンドを実行して更新可能な最新版にアップデート可能なモジュールを見つけて更新していくわけだが。
めんどくさい。
npm-check-updates 略して、 ncu というパッケージがある。
これを使うと package.json の中身を更新してくれるわけで、便利そうである。
npm install npm-check-updates npx ncu -u npm update npm install
これで、一通りのアップデートが可能になる。思ってたより楽である。
開発者が想定したpackage.json を更新するのである。当然であるが、依存モジュールをアップデートすると、decrepcated なメソッドやバージョン差異による動作不良に悩まされることもあるので注意が必要である。
which コマンドを使うと 環境変数 PATH にあるコマンドのうち、最初に見つかったもの(実行されるもの)を表示してくれます。
which python
どのコマンドが実行されるのか調べるのに便利ですし、よく使ってると思います。
pyenv や nvm や rbenv などを使っていると、あれ?バージョンが合わない?パスがおかしい????
などという事がよくあります。
こういうときにPATHに含まれる全てのもの列挙できたらと思いませんか
コマンドがいくつも同じ名前で入っている場合に、全てを表示してくれます。
表示順は、PATHの優先順位が高い順に表示してくれます。
takuya@-api$ which -a grep /Users/takuya/.bin/grep /usr/bin/grep
takuya@-api$ which -a java /usr/bin/java
takuya@-api$ which -a python /Users/takuya/.pyenv/shims/python /usr/local/bin/python /usr/bin/python
これをすることで、 python が同名でいくつもあることがわかったり、$PATHに同じパスが重複していたり、bashrc や pipenv shell などで .bashrc の意図した動作にならない。 順序がおかしくなっていることに気づくことができます。
https://takuya-1st.hatenablog.jp/entry/2017/04/06/153337
systemd で作ったサービスを定期的に再起動したい。
定期的に再起動する必要があるのか。と問われれば、私自身も答えに窮するのだけれど。
今回は pip install しているpython パッケージや npm run で起動している元になっている npm/node_moduleを、定期的更新して再起動をしたいなと思ったんですよ。
[Service] Restart=always RuntimeMaxSec=864000
unit ファイルに上記のように書くと定期的に再起動がかかる。
RuntimeMaxSec=60
RuntimeMaxSec をつけることで、サービスのプロセスの継続実行時間を秒単位で指定できる。今回は 60*60*24*10 = 864,000
を指定した。
Restart=always
Restart の設定を alwaysにしておくと、サービスに定義したプロセスが異常終了など、終了したときに自動再実行によりプロセスが起動している状態を維持してくれる。
これらを組合わたら、定期的に再起動のコマンドが実現する
[Service] Restart=always RuntimeMaxSec=864000
組み合わせてしまうと、指定時間経過後にプロセスが終了して、always により再度サーバーが実行される。
crontab に書いてしまうと、管理がsystemd と分かれてしまうのであまり好ましくないし。
サーバーが自分を自分で再起動するように sleep を使った定期的に再起動が仕込まれた起動用python スクリプトを書くのは煩雑すぎるし。
systemd の timer を使っても、設定が2つに別れてしまって面倒だ。
今回採用した方法だと、設定ファイルが1つにまとまるので書き捨てて仕様書を残さなくても気付けるメリットが有る。
systemd の設計者は、こういう利用は想定外なんだろうと思うんだけど、1箇所に必要な設定が集まるのは嬉しい
npm でパッケージをいれて、npm run で動かせるサーバーアプリケーションがおおいけど、パッケージはlock されて基本的には更新を考慮してない。
debian の apt などは セキュリティ・パッチが含まれた deb などをaptの設定自動的にダウンロードして再実行してくれる。ほんとうにこの差は大きいと思う。
gitlab とは自動的に自分で自分を更新してくれるし、そういう意味で node のnpm で作られたサーバーって今後危ういなぁなどと思う。
再起動するサービスと、タイマー、この2つのユニットを分けて書くときは、ネットにいっぱいサンプルが転がってる。
うちのサイトでの作成サンプルは、この記事でtimer/serviceのunits を使ってsystemdのユニットを定期的に起動している。
分ける場合のサンプル → https://takuya-1st.hatenablog.jp/entry/2020/04/09/051239
分ける場合のtimer の書式 → https://takuya-1st.hatenablog.jp/entry/2020/04/24/032822
再起動スクリプト+Service+Timer+タイマ書式の4つが必要になる。こういうことを考えるのが面倒なので再起動がすぐ終わるServiceなら今回紹介しているMaxTimeによる再起動が楽だと思うの。
かんたんな、初期値nullチェックとかで三項演算子的なことをよくやります。
bash でもやりたいなと思って調べててみたけど、なかった(あったので追記書きます。)。
条件分岐を使って原始的な手法がsh/bash で使えるのでご紹介。
[[ $var == abc ]] && echo OK || echo NG
#!/bin/bash ## 変数 a=1 echo TRUE になる場合 [[ $a == 1 ]] && echo TRUE || echo FALSE echo FALSE が実行される場合 [[ $a == 0 ]] && echo TRUE || echo FALSE
将来のアップデートでbash には搭載されるかもしれないけど、sh には永遠に搭載されないだろし
条件判定を組み合わせて三項演算子っぽく記述できる方法は便利だし採用していきたい。
三項演算子はsh にはなくbash 独自の機能 (( ))
を使えば、書くことが出来ました。
a=1 b=$(( a !=0 ? -1 : 0 ))
ちなみに、(( ))
のArithmetic expressions を書くときは、変数に$を付けない。
実際に動かしてみた例はこちら。
takuya@~$ unset a b takuya@~$ a=1 takuya@~$ b=$(( a !=0 ? -1 : 0 )) takuya@~$ echo $b -1 takuya@~$ takuya@~$ unset a b takuya@~$ a=0 takuya@~$ b=$(( a !=0 ? -1 : 0 )) takuya@~$ echo $b 0
三項演算子ありました。 (( ))
を使えば、C言語スタイルの演算ができるので、もしやと思って調べたら・・・
systemd でdaemon を起動しているのですが、pip 関連でアップデートが頻繁にあるモジュールだと、前もって更新してあげないとエラーになることがる。
ExecStartPre を使うと、起動前に実行してくれるようだ。
ExecStartPre=, ExecStartPost= Additional commands that are executed before or after the command in ExecStart=, respectively. Syntax is the same as for ExecStart=, except that multiple command lines are allowed and the commands are executed one after the other, serially.
ExecStartPreを複数書けばいいらしい
pipenv に入れた pip や requirements.txt をDaemonの起動前に、更新をするように書きました。
[Unit] Description=Splattoon splatnet2ink [Service] WorkingDirectory=/PATH/TO/project ExecStartPre=/PATH/bin/python /PATH/TO/pipenv/bin/pip install --upgrade pip ExecStartPre=/PATH/TO/pipenv/bin/python /PATH/TO/pipenv/bin/pip install --upgrade -r requirements.txt ExecStart=/PATH/TO/pipenv//bin/python /PATH/TO/pipenv/daemon.py -M [Install] WantedBy=default.target
これまでは、ライブラリ更新処理を、別途 timer にしてたり、更新後再起動をタイマーにしてたのですが、不便でした。
これで、PCを起動時、ユーザー systemd 空間なら、ログイン時に更新されるはず。だから timer 関連のsystemd ファイルが減って管理が楽になりそうです。
https://www.freedesktop.org/software/systemd/man/systemd.service.html