A Micro Toolbox

ソフトウェアのニッチな問題の対処記録です

curlとChromeのコマンドラインオプションで名前解決

Webアプリ検証で、ドメインやホスト名を一時的に非公開サーバーに向けてアクセスしたいときがある。 /etc/hostsに設定追加したり、Hostヘッダーを書き換えたりして対処できることも多いが、ここでは別案としてcurlChromeコマンドラインオプションで名前解決する方法。

curlの場合

--resolve ドメイン:ポート:IPアドレス

複数のドメイン:ポートを指定するときは「--resolve ドメイン:ポート:IPアドレス」を繰り返す。

$ curl -s --resolve example.com:8000:127.0.0.1 --resolve example.org:8000:127.0.0.1 http://example.com:8000 | grep h1
<h1>Directory listing for /</h1>
$
$ curl -s --resolve example.com:8000:127.0.0.1 --resolve example.org:8000:127.0.0.1 http://example.org:8000 | grep h1
<h1>Directory listing for /</h1>
$

Chromeの場合

--host-resolver-rules="MAP ドメイン:ポート IPアドレス:ポート"

最初のポートはブラウザからアクセスするときのもの。指定しなければ全ポートのアクセスがIPアドレスで指定したサーバーに行く。 二番目のポートは実際にWebアプリが待ち受けているポート。

複数指定するときは「,」区切りで「MAP ドメイン:ポート IPアドレス:ポート」を繰り返す。

ショートカットを作ると楽。

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --incognito --user-data-dir=C:\path\to\chrome-profiles\internal-test --host-resolver-rules="MAP example.com:8080 127.0.0.1:8000, MAP *.example.org 127.0.0.1:8000"

Chromeexample.com:8080にアクセスした様子

16進記法で指定した色を取り出すとrgb()関数になる

CSSで色を16進数で書いて

<span id="colortest" style="color:#ff9933;">orange<span>

JavaScriptで取り出すと

const colorspan = document.getElementById("colortest");
console.log(colortest.style.color);
console.log(colortest.style.cssText);

rgb()関数表記になっている。

rgb(255, 153, 51)
color: rgb(255, 153, 51)

CSSの仕様によるものらしい。

CSS Color Module Level 4 https://drafts.csswg.org/css-color/#resolving-color-values

日本語訳 https://triple-underscore.github.io/css-color-ja.html#rgb-functions

nzip: 入れ子のzipファイルを展開する

あるzipファイルを展開すると中にはzipファイルがあって、そのまた中にはzipファイルがあって、マトリョーシカ的になっていることがある。 例えば、JARファイルに含まれる依存ライブラリのJARが提供するクラスも一括で見たいとき、一階層ずつ展開していくのはつらい。

nzipというJava製ツールを試してみたら便利だった。 github.com

使い方

インストール

git cloneするだけ。

$ git clone https://github.com/ankitkaushal/nzip.git

実行方法

nzip.jarが本体なのでJavaで実行する。

$ java -jar /path/to/nzip/nzip.jar -h
usage: nzip
 -c <arg>   required please enter the command name - list,extract or
            compress
 -e <arg>   please enter the zip extensions separated by comma
 -h         help
 -s <arg>   required please enter source directory or file
 -t <arg>   please enter target file or directory
 -u <arg>   please enter the suffix for extracting zip directories
$

テスト用に入れ子zipファイルを作成

zipコマンドでsample1.txt -> nested1.zip -> nested2.zip -> nested3.zipとzipの中にzipを入れていく。

$ zip nested1.zip sample.txt
  adding: sample.txt (stored 0%)
$ zipinfo -1 nested1.zip
sample.txt
$
$ zip nested2.zip nested1.zip
  adding: nested1.zip (stored 0%)
$ zipinfo -1 nested2.zip
nested1.zip
$
$ zip nested3.zip nested2.zip
  adding: nested2.zip (stored 0%)
$ zipinfo -1 nested3.zip
nested2.zip
$
$ rm sample.txt nested1.zip nested2.zip

展開せずにファイル一覧を表示

展開しないで中身だけ知りたいとき助かる。

$ java -jar /path/to/nzip/nzip.jar -c list -s nested3.zip
/nested2.zip
/nested2.zip/nested1.zip
/nested2.zip/nested1.zip/sample.txt
$

入れ子zipを一括展開

デフォルトではzipを展開してできたディレクトリに拡張子.nzipがつく。

$ java -jar /path/to/nzip/nzip.jar -c extract -s nested3.zip -t .
command has executed successfully
$
$ tree nested2.zip.nzip
nested2.zip.nzip
└── nested1.zip.nzip
    └── sample.txt

1 directory, 1 file
$

出力先ディレクトリや展開したディレクトリにつける拡張子を指定できる。

$ java -jar /path/to/nzip/nzip.jar -c extract -s nested3.zip -t nested3 -u .dir
command has executed successfully
$
$ tree nested3
nested3
└── nested2.zip.dir
    └── nested1.zip.dir
        └── sample.txt

2 directories, 1 file
$

比較のためunzipで展開した場合

$ ls
nested3.zip
$
$ unzip nested3.zip
Archive:  nested3.zip
 extracting: nested2.zip
$ ls
nested2.zip  nested3.zip
$
$ unzip nested2.zip
Archive:  nested2.zip
 extracting: nested1.zip
$ ls
nested1.zip  nested2.zip  nested3.zip
$
$ unzip nested1.zip
Archive:  nested1.zip
 extracting: sample.txt
$ ls
nested1.zip  nested2.zip  nested3.zip  sample.txt
$

zipとみなす拡張子を指定

デフォルトで.war、.ear、.jar、.zipをzipファイルとみなして展開するとのこと。それ以外の拡張子でも-eオプションで指定できる。

適当に拡張子を.z_i_pにしてzipファイルに含めてみる。

$ touch sample.txt
$ zip demo.z_i_p sample.txt
  adding: sample.txt (stored 0%)
$
$ zip test.zip demo.z_i_p
  adding: demo.z_i_p (deflated 47%)
$
$ zipinfo -1 test.zip
demo.z_i_p
$

デフォルトでは展開されない。

$ java -jar /path/to/nzip/nzip.jar -c list -s test.zip
/demo.z_i_p
$

-e z_i_pを指定すると展開される。

$ java -jar /path/to/nzip/nzip.jar -c list -s test.zip -e z_i_p
/demo.z_i_p
/demo.z_i_p/sample.txt
$

vmstatの出力に時刻を付けてファイル保存(ミリ秒)

Linuxでvmstatの1行ごとに時刻を付けるときにミリ秒まで入れる。

$ vmstat 3 | ruby -ne 'print Time.now.strftime("%X.%3N #{$_}"); STDOUT.flush' | tee vmstat_log.txt
18:44:25.141 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
18:44:25.141  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
18:44:25.141  1  0      0 23715472 133952 2093676    0    0    12   166   34  170  5  1 94  0  0
18:44:27.991  0  0      0 23699344 133952 2093664    0    0     0     0  195 1590  0  0 100  0  0

straceやinotifywaitにも使える。

$ strace sleep 3 |& ruby -ne 'print Time.now.strftime("%X.%3N #{$_}"); STDOUT.flush' | tee trace_sleep3.txt
16:55:38.939 execve("/usr/bin/sleep", ["sleep", "3"], 0x7ffeaad126a8 /* 29 vars */) = 0
16:55:38.939 brk(NULL)                               = 0x55df60aa7000
16:55:38.939 arch_prctl(0x3001 /* ARCH_??? */, 0x7fff72025b60) = -1 EINVAL (Invalid argument)
16:55:38.939 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff2c632a000
16:55:38.939 access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
16:55:38.939 openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
16:55:38.939 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=23031, ...}, AT_EMPTY_PATH) = 0
16:55:38.939 mmap(NULL, 23031, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff2c6324000
16:55:38.939 close(3)                                = 0
16:55:38.939 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
16:55:38.939 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\237\2\0\0\0\0\0"..., 832) = 832
16:55:38.939 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
16:55:38.939 pread64(3, "\4\0\0\0 \0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 48, 848) = 48
16:55:38.939 pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0i8\235HZ\227\223\333\350s\360\352,\223\340."..., 68, 896) = 68
16:55:38.939 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=2216304, ...}, AT_EMPTY_PATH) = 0
16:55:38.939 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
16:55:38.939 mmap(NULL, 2260560, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ff2c60fc000
16:55:38.939 mmap(0x7ff2c6124000, 1658880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7ff2c6124000
16:55:38.939 mmap(0x7ff2c62b9000, 360448, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7ff2c62b9000
16:55:38.939 mmap(0x7ff2c6311000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x214000) = 0x7ff2c6311000
16:55:38.939 mmap(0x7ff2c6317000, 52816, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ff2c6317000
16:55:38.939 close(3)                                = 0
16:55:38.939 mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff2c60f9000
16:55:38.939 arch_prctl(ARCH_SET_FS, 0x7ff2c60f9740) = 0
16:55:38.939 set_tid_address(0x7ff2c60f9a10)         = 26285
16:55:38.939 set_robust_list(0x7ff2c60f9a20, 24)     = 0
16:55:38.939 rseq(0x7ff2c60fa0e0, 0x20, 0, 0x53053053) = 0
16:55:38.939 mprotect(0x7ff2c6311000, 16384, PROT_READ) = 0
16:55:38.939 mprotect(0x55df60214000, 4096, PROT_READ) = 0
16:55:38.939 mprotect(0x7ff2c6364000, 8192, PROT_READ) = 0
16:55:38.939 prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
16:55:38.939 munmap(0x7ff2c6324000, 23031)           = 0
16:55:38.939 getrandom("\x7e\xdb\x66\x5e\x19\x12\x13\x89", 8, GRND_NONBLOCK) = 8
16:55:38.939 brk(NULL)                               = 0x55df60aa7000
16:55:38.939 brk(0x55df60ac8000)                     = 0x55df60ac8000
16:55:38.939 openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
16:55:38.939 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=5712208, ...}, AT_EMPTY_PATH) = 0
16:55:38.939 mmap(NULL, 5712208, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff2c5b86000
16:55:38.939 close(3)                                = 0
16:55:41.785 clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=3, tv_nsec=0}, 0x7fff72025bb0) = 0
16:55:41.786 close(1)                                = 0
16:55:41.786 close(2)                                = 0
16:55:41.787 exit_group(0)                           = ?
16:55:41.788 +++ exited with 0 +++
$

秒単位よりもう少し細かいタイミングが欲しいときに。

サクラエディタにtextlintによる文章校正マクロを登録する

サクラエディタからtextlintを実行して日本語文章のチェックができるように設定する。

試した環境: Windows 10 + サクラエディタ 2.2.0.1 + Node.JS 12.16.1

1. textlintをインストール

インストール先のディレクトリを作成する。 このディレクトリはNode.jsの新規プロジェクトディレクトリになるが、特に何か作る予定はないのでディレクトリ名は適当でよい(ただし、textlint以外)。

> npm init -y
> npm install -D textlint

2. ルールプリセットを設定

> npm install -D textlint-rule-preset-ja-technical-writing
> npx textlint --init
.textlintrc is created.
{
  "filters": {},
  "rules": {
    "preset-ja-technical-writing": true
  }
}

3. textlintの起動バッチを作成

同じディレクトリにrun_textlint.batという名前でバッチファイルを作成する。

pushd %~dp0
npx textlint --stdin --no-color
popd

4. サクラエディタのマクロを作成

次の内容でtextlint.macという名前のファイルを作成する。パスはバッチファイルの置き場所にあわせて調整。

既にほかにマクロを作成していれば同じディレクトリに保存する。なければ場所は問わない。

S_ExecCommand('C:\\path\\to\\run_textlint.bat', 389);

389 = 0x185。UTF-8で標準入出力を使う。

参考: https://sakura-editor.github.io/help/HLP000103.html

4. サクラエディタにマクロを登録

設定 > 共通設定 > マクロを開く。

マクロ一覧の参照から、マクロを保存したディレクトリを選択する。

Fileのプルダウンにtextlint.macが現れるので選択する。

設定をクリック。

これで、サクラエディタに何かテキストを打ち込み、チェックしたい範囲を選択して、ツール > 登録済みマクロ > textlintを実行するとtextlintによるチェック結果が別ウィンドウ(テキスト)で出力される。

スタックトレースを削る

スレッドダンプやログに出力されるスタックトレースはしばしば長大になる。


長大なスタックトレースを解析するとき、あまり注目しない行を削ると見通しがよくなる。

あまり注目しない行をどう判定するかが問題だが、個人的経験では、同じパッケージ内での呼び出しを省略すると3割くらい削れる。


機械的作業なので、コピペでできるようにしてみた。

https://github.com/hashimoton/cauldron


「- locked」の前は省略しないとかdoFilter()が含まれたら省略する(サーブレットフィルタを意識したもの)とか、いくつかルールを追加している。


例えばこれが

"Worker-8: reload maven project" #48 prio=5 os_prio=0 tid=0x0000000023eb4000 nid=0x2f78 runnable [0x000000002f92b000]
java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:170)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
    at sun.security.ssl.InputRecord.read(InputRecord.java:503)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
    - locked <0x00000000d2b1a418> (a java.lang.Object)
    at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:930)
    at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
    - locked <0x00000000d2b38328> (a sun.security.ssl.AppInputStream)
    at okio.Okio$2.read(Okio.java:140)
    at okio.AsyncTimeout$2.read(AsyncTimeout.java:237)
    at okio.RealBufferedSource.indexOf(RealBufferedSource.java:358)
    at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:230)

こうなる。

"Worker-8: reload maven project" #48 prio=5 os_prio=0 tid=0x0000000023eb4000 nid=0x2f78 runnable [0x000000002f92b000]
java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
...
    at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
    at sun.security.ssl.InputRecord.read(InputRecord.java:503)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
    - locked <0x00000000d2b1a418> (a java.lang.Object)
    at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:930)
    at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
    - locked <0x00000000d2b38328> (a sun.security.ssl.AppInputStream)
    at okio.Okio$2.read(Okio.java:140)
...


Pythonで本格的にやっているのがあった。

https://github.com/nir0s/backtrace

Javaの特定パッケージに着目するアプローチ。

https://habr.com/en/post/480268/

pacman -Syu後にMSYS2が起動しない

結論から書くと、PC再起動で復活した。

 

 

まず先に、全パッケージ更新がPGP keyのエラーで失敗した。

 

$ pacman -Syu

...

error: msys: key "4A6129F4E4B84AE46ED7F635628F528CF3053E04" is unknown
:: Import PGP key 4A6129F4E4B84AE46ED7F635628F528CF3053E04? [Y/n] Y
error: key "4A6129F4E4B84AE46ED7F635628F528CF3053E04" could not be looked up remotely
error: database 'msys' is not valid (invalid or corrupted database (PGP signature))

 

同じ症状の方の記事を参考にして、単体パッケージ更新に成功した。

[msys2] Package install Error | アスペ姉とITエンジニアの将来

 

$ curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz
$ curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig
$ pacman-key --verify msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig
$ pacman -U --config <(echo) msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz

$ pacman -S git

 

続いて再度全パッケージ更新。

 

$ pacman -Syu

...
warning: terminate MSYS2 without returning to shell and check for updates again
warning: for example close your terminal window instead of calling exit

 

パッケージ更新が終了して、メッセージに出ているようにMSYSのウィンドウを閉じた。

 

 

この後、再度MSYSを起動したら一瞬で落ちた。

 

コマンドプロンプトから実行しても何もメッセージが出ない。

 

msys2> msys2_shell.cmd

msys2>

 

bashを実行してみたらメッセージが出てきた。

 

msys2> usr\bin\bash.exe
1 [main] bash (17276) shared_info::initialize: size of shared memory region changed from 49080 to 40888

msys2>

 

調べると、MSYS2のプロセスが残っているらしい。

 

MSYS2 installation - MSYS2

If your MSYS2 is unable to start after an upgrade, it's possible you just have some lingering MSYS2 processes (loaded with an older version of the runtime) that are conflicting with the processes you're trying to start. Hunt down these processes in your favorite task manager and kill them, or just reboot your system.

 

PCを再起動して、無事に起動するようになった。

で、これまで何度か同じことをしたのを思い出した。