それマグで!

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

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

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

date コマンドでミリ秒→日付、int 秒 → 日付へそれぞれ数値を日付表記にフォーマットする

int 秒を日付にするには

引数 -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 コマンドでフォーマットの方法は、過去記事があるので。参照

dateコマンドでiso/rfc日付時刻タイムゾーンをぱぱっとフォーマットして作る - それマグで!

逆に int 秒がほしいとき

dateコマンドで unix epoch time の int 秒を取得する - それマグで!

npm で作られたプロジェクトの依存モジュールを更新する npm-check-updates

npm で作ったパッケージのnode_module の更新をしたい

npm でインストールしたパッケージはどうも使い捨ての傾向があり、アップデートを継続するにはちょっと手間が必要で。

更新可能なパッケージをを見つけるには

npm のサブコマンドを使えばできる

npm update 
npm outdated

これらのコマンドを実行して更新可能な最新版にアップデート可能なモジュールを見つけて更新していくわけだが。

めんどくさい。

npm-check-updates

npm-check-updates 略して、 ncu というパッケージがある。

これを使うと package.json の中身を更新してくれるわけで、便利そうである。

アップデート手順

npm install npm-check-updates
npx ncu -u 
npm update 
npm install 

これで、一通りのアップデートが可能になる。思ってたより楽である。

開発者が想定したpackage.json を更新するのである。当然であるが、依存モジュールをアップデートすると、decrepcated なメソッドやバージョン差異による動作不良に悩まされることもあるので注意が必要である。

参考資料

which コマンドでPATHにある同名のコマンドを全部列挙する

PATH の優先順位に悩まされるたときに which

which コマンドを使うと 環境変数 PATH にあるコマンドのうち、最初に見つかったもの(実行されるもの)を表示してくれます。

which python 

どのコマンドが実行されるのか調べるのに便利ですし、よく使ってると思います。

同名のコマンドで上書きされてないか?

pyenv や nvm や rbenv などを使っていると、あれ?バージョンが合わない?パスがおかしい????

などという事がよくあります。

こういうときにPATHに含まれる全てのもの列挙できたらと思いませんか

すべてを表示する which -a / --all

コマンドがいくつも同じ名前で入っている場合に、全てを表示してくれます。

表示順は、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

参考資料

  • which -h

systemd のdaemon のサービスを定期的に再起動する unit ファイルの書き方-timerを省略する

systemd のサービスを定期的に再起動する

systemd で作ったサービスを定期的に再起動したい。

定期的に再起動する必要があるのか。と問われれば、私自身も答えに窮するのだけれど。

今回は pip install しているpython パッケージや npm run で起動している元になっている npm/node_moduleを、定期的更新して再起動をしたいなと思ったんですよ。

systemd の書き方

[Service]
Restart=always
RuntimeMaxSec=864000

unit ファイルに上記のように書くと定期的に再起動がかかる。

仕組みの説明

RuntimeMaxSec による実行時間の制限

RuntimeMaxSec=60

RuntimeMaxSec をつけることで、サービスのプロセスの継続実行時間を秒単位で指定できる。今回は 60*60*24*10 = 864,000 を指定した。

Restart による再起動の設定

Restart=always

Restart の設定を alwaysにしておくと、サービスに定義したプロセスが異常終了など、終了したときに自動再実行によりプロセスが起動している状態を維持してくれる。

組合わたら、定期的に再起動

これらを組合わたら、定期的に再起動のコマンドが実現する

[Service]
Restart=always
RuntimeMaxSec=864000

組み合わせてしまうと、指定時間経過後にプロセスが終了して、always により再度サーバーが実行される。

検討したその他の手法との比較など

crontab に書いてしまうと、管理がsystemd と分かれてしまうのであまり好ましくないし。

サーバーが自分を自分で再起動するように sleep を使った定期的に再起動が仕込まれた起動用python スクリプトを書くのは煩雑すぎるし。

systemd の timer を使っても、設定が2つに別れてしまって面倒だ。

今回採用した方法だと、設定ファイルが1つにまとまるので書き捨てて仕様書を残さなくても気付けるメリットが有る。

systemd の設計者は、こういう利用は想定外なんだろうと思うんだけど、1箇所に必要な設定が集まるのは嬉しい

pip や npm の更新が辛い

npm でパッケージをいれて、npm run で動かせるサーバーアプリケーションがおおいけど、パッケージはlock されて基本的には更新を考慮してない。

debian の apt などは セキュリティ・パッチが含まれた deb などをaptの設定自動的にダウンロードして再実行してくれる。ほんとうにこの差は大きいと思う。

gitlab とは自動的に自分で自分を更新してくれるし、そういう意味で node のnpm で作られたサーバーって今後危ういなぁなどと思う。

service と timer を分けて書くとき

再起動するサービスと、タイマー、この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による再起動が楽だと思うの。

関連資料

参考資料

bash で三項演算子っぽく処理を書くには

bash でも三項演算子を使いたい

かんたんな、初期値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 に存在しない

将来のアップデートで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

2019-08-29 訂正

三項演算子ありました。 (( )) を使えば、C言語スタイルの演算ができるので、もしやと思って調べたら・・・

参考資料

https://wiki.bash-hackers.org/syntax/arith_expr

systemdのジョブの起動前、起動後に処理を記述する preExec / PostExec

systemd で自動起動するファイルを記述したが pip のアップデートで苦労する

systemd でdaemon を起動しているのですが、pip 関連でアップデートが頻繁にあるモジュールだと、前もって更新してあげないとエラーになることがる。

systemd で事前処理・事後処理を書けないか調べてみたらあった

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

ついに牙を向いたPublic DNS

Cloudflare の 1.1.1.1 が dns 応答を拒否し始める。

巨大になった組織の宿命というか、世間のレベルより「踏み込んだ」対応をして自粛をしないとダメなんだろうけど、管理は、インターネットな文化と相容れないと思ってた私の脳みそは時代遅れで腐っているのでしょうかと。

www.itmedia.co.jp

DoH も危ない

DNS over HTTPSFirefox のも Cloudflare が請負っているので、あちらも同じことになると思う。

自前で dns が必要

public dns が使えないなら、昔のように、自前で public dns を建てるしか無い。

unbound をインストールするしか。

しかし、自宅ならともかく、4G/5Gのモバイルネットワークでどうするんだよこれ。 DNSを支配される悪夢だ・・・