それマグで!

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

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

laravel のマイグレーションで特定のmigration のファイル名指定して、一つだけ再度・何度も実行したい

laravel でmigrate するとき、特定のファイルだけを実行したい

migrate refresh とかだと全部のテーブルが再生成されちゃうので、別のテーブルデータを消さずに特定のテーブルだけを再構築したい。

サンプル

指定したマイグレーションのファイルだけを実行する

artisan migrate:refresh --step=1  --path=/database/migrations/2019_09_18_182637_create_users_table.php 

指定方法

上記のコマンドは、次のように分解できる。

## マイグレーションを全部実行する
php artisan migrate:refresh 

これと個数を組み合わせ

## マイグレーションを先頭から1つだけ
php artisan migrate:refresh  --step=1

さらにパスを指定する。

## マイグレーションを指定したファイルから1つだけ
php artisan migrate:refresh  --step=1 --path=/database/migrations/ファイル名

パスの設定や step の指定を忘れて migrate:refresh すると全部消えちゃうので注意が必要。

どういうときに使うのか

テーブルを追加するときにアレコレ試しているローカル環境で使う。

いちいち seeder や seed を使ってデータを追加するのも面倒なので。

テーブルの定義のマイグレーションを、指定して再実行したり、テーブル定義を書き直したりしたときに使います。

これを使うことで、テーブル定義のを書いながら何度も試せるので、マイグレーションをfresh でゼロからしてしまうことなくなるので便利です。

laravel だとテーブル定義を作りながら考えられるのはいいことだと思います。

併せて使いたい status コマンド

migrate:status をつかえば、いまどこまでmigration が適用されているかわかる。

artisan migrate:status

マイグレーションの適用結果はデータベースに格納されている。それをコマンドから見ることができる。

参考資料

https://stackoverflow.com/questions/45473624/laravel-5-4-specific-table-migration

lvm で容量拡張

よく使うものだけ抜粋

lvm のアレコレはすっ飛ばして、よく使うコマンドだけを抜粋してメモに残します。

余っているpv から容量を追加する

pv と vg に容量は割り当て済みとする。

sudo lvextend -L +10g vg/temp_cache

終わったら、ext4 をリサイズする。

sudo resize2fs /dev/mapper/my-temp_cache

関連資料

詳細はこちら

LVMの lvextend でLVを拡張する - それマグで!

chrome で印刷プレビューのCSSをデバッグ表示するには

印刷プレビューのCSSを触りたい

印刷プレビューの media type print css をいじったりチェックしたり、デバッグしたり、表示おかしいので直したいときがあります。

CSSのプリントを印刷プレビューでチェックするのは途方も無い時間がかかる。

そこで、印刷プレビューでレンダリングしてくれるモードが、開発ツールになる。

chrome の開発ツールでメニューからRenderingを選ぶ

開発ツールの下側のメニュー → レンダリングを選ぶ

f:id:takuya_1st:20190918001744p:plain

media type を print にする

プリントにすると、印刷プレビューがブラウザに表示される。これで楽になるね!

f:id:takuya_1st:20190918001804p:plain

PostgreSQLでtimestamp/now() を文字列にする char キャスト

PostgreSQL でタイムスタンプを文字列として取り出したい

char にキャストするときに長さをつける

now() の場合

select now()::char(30);

実行結果

sample> select now()::char(30);
+--------------------------------+
| now                            |
|--------------------------------|
| 2019-09-13 15:27:51.427441+00  |
+--------------------------------+
SELECT 1
Time: 0.086s

current_timestamp の場合

select current_timestamp::char(29)

実行結果

sample> select current_timestamp::char(29)
+-------------------------------+
| now                           |
|-------------------------------|
| 2019-09-13 15:29:01.630241+00 |
+-------------------------------+
SELECT 1
Time: 0.067s
sample>

あんまり美しいやり方ではないけれど

PostgreSQLでランダムなINTを生成する

ランダムなINTがほしい

cast の場合はこれ

select cast(random()*100 as integer);

::int を使ったキャストを使う場合はこんな感じ

floor(random() * 1000 + 1)::int;

参考資料

https://www.postgresql.jp/document/9.4/html/functions-math.html

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