A Micro Toolbox

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

MSYS上のcurlで/から始まる値をPOSTする

Git for Windowsbashcurlを使うときに、フォームパラメータの値が「/」から始まると補完されたパスがサーバに送られる。

 

例えば、次のようにすると、

$ curl -F'param1=/path/to/file' http://localhost:8000/

サーバ側には

param1=C:/tools/console/Git/path/to/file

が送られる。

 

調べたら、MSYSがパスの変換をしていた。

http://www.mingw.org/wiki/Posix_path_conversion

 

値の末尾に「;」をつければ

$ curl -F'param1=/path/to/file;' http://localhost:8000/

変換されずに

param1=/path/to/file

が送られる。

 

2021-01-03 追記

環境変数で変換を止める設定ができた。

$ export MSYS2_ARG_CONV_EXCL="*"

https://www.msys2.org/docs/filesystem-paths/

 

pwdx: プロセスの作業ディレクトリを表示

バージョンや環境設定違いのプログラムを同一サーバ上にいくつも立ち上げていると、それぞれのプロセスの作業ディレクトリを確認したくなるときがある。

 

やり方としては、/proc/プロセスID/cwdのシンボリックリンク先を見ればいい。

$ readlink /proc/$PID/cwd

 

最近になって、pwdxというまさにこのためのコマンドが存在することを知った。

https://gitlab.com/procps-ng/procps

 

$ ps
PID TTY TIME CMD
25562 pts/0 00:00:00 bash
25808 pts/0 00:00:00 ps
$ pwdx 25562
25562: /home/foo
$

 

端的で便利。

sudoは子プロセスを作る

とあるコマンドをsudo経由で実行したらpsで2つプロセスが見えた。

 

純化した実行例:

$ sudo sleep 300 &
[1] 26061

$

$ ps -ef | grep [s]leep
root 26061 18849 0 18:44 pts/1 00:00:00 sudo sleep 300
root 26066 26061 0 18:44 pts/1 00:00:00 sleep 300
$

 

sudoのman pageにしっかり書いてあった。

https://linuxjm.osdn.jp/html/sudo/man8/sudo.8.html

sudo は、コマンドを実行するとき、まず fork(2) を呼び、 実行環境を上記のように設定してから、子プロセスで execve システムコールを呼び出す。 メインの sudo プロセスは、コマンドが完了するまで wait し、完了したら、 コマンドの終了ステータスをセキュリティポリシーの close 関数に渡してから、 終了する。

 

テキストファイルのビットマップ表示

grepに触発されて、バイナリエディタBzのビットマップ表示をテキストでやってみた。

 

作ったツール(txt2img)のソースを画像にしたもの。

 

f:id:m0t0m0t0:20200223042206p:plain

ログファイルとかスレッドダンプとか長いファイルを俯瞰するのにいいかもしれない。

MinitestでOpen3.capture3の出力先頭に「# encoding: UTF-8」が入る

Open3.capture3で取得した標準出力の文字列をMinitestで使ったら、先頭に「# encoding: UTF-8」が入ってくることがあった。

例えば下記のテストは失敗するのだけど、expectedとactualの差分を見るとactualの先頭行が「# encoding: UTF-8」になっている。

# coding: utf-8

require 'minitest'
require 'minitest/autorun'
require 'open3'

class TestCapture3 < MiniTest::Test

  def test_stdout
    output, error, status = Open3.capture3("cat -", stdin_data: "")
    assert_equal "\n", output
  end

end
$ ruby test_capture3.rb
Run options: --seed 56761

# Running:

F

Finished in 0.232475s, 4.3015 runs/s, 4.3015 assertions/s.

  1) Failure:
TestCapture3#test_stdout [test_capture3.rb:11]:
--- expected
+++ actual
@@ -1,3 +1 @@
-# encoding: UTF-8
-"
-"
+""


1 runs, 1 assertions, 1 failures, 0 errors, 0 skips
$

上記の場合、expectedを""にすれば何も問題なくテストは成功するものの気持ち悪さが残る。

対処方法を調べたところ、冒頭で外部エンコーディングを明示的に指定することで「# encoding: UTF-8」が入らなくなった。

Encoding.default_external = 'utf-8'

実行環境: ruby 2.6.5p114 (2019-10-01 revision 67812) [x64-mingw32] + minitest (5.11.3)

Windows 10のAnaconda付属pipでWARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.

Windows 10でAnaconda付属のpipを実行したら、SSLモジュールが見つからないとのことでpip installできなかった。

 

> pip install docopt
WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
Collecting docopt
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /simple/docopt/

...

Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.")) - skipping

 

下記を読むとOpenSSLのライブラリが必要らしい。

https://conda.io/projects/conda/en/latest/user-guide/troubleshooting.html#ssl-connection-errors

 

自分の場合、PATHに指定しているフォルダには入っていなかった。

 

Anacondaのインストールフォルダ内でlibsslを探したところ、インストールフォルダ\Library\bin\libssl-1_1-x64.dllが見つかった。

 

PATHにインストールフォルダ\Library\bin\を追加してコマンドプロンプトを立ち上げなおしたら無事実行できた。

 

2>pip install docopt
Collecting docopt
Downloading https://files.pythonhosted.org/packages/a2/55/8f8cab2afd404cf578136ef2cc5dfb50baa1761b68c9da1fb1e4eed343c9/docopt-0.6.2.tar.gz
Building wheels for collected packages: docopt
Building wheel for docopt (setup.py) ... done
Stored in directory: C:\Users\foobar\AppData\Local\pip\Cache\wheels\9b\04\dd\7daf4150b6d9b12949298737de9431a324d4b797ffd63f526e
Successfully built docopt
Installing collected packages: docopt
Successfully installed docopt-0.6.2

 

 

RubyInstaller付属のMinttyを右クリックメニューで開く

RubyInstallerでRuby 2.6.5+DevKitをインストールしたらMSYS2が入った。

この機会にWindowsでのBash環境をGit for Windowsから変えてみた。

 

 

C:\Ruby26-x64\msys64にPATHを通す。

 

C:\Ruby26-x64\msys64\msys2.iniで次の行のコメントを外す。

 

CHERE_INVOKING=1

 

これでエクスプローラで開いているフォルダのアドレスバーにmsys2と入れれば、そのフォルダでBashが起動するようになった。

 

 

が、フォルダの何もないところの右クリックメニューからBashを開こうとしてはまった。

 

レジストリエディタでキーを作成。

 

HKEY_CLASSES_ROOT\Directory\Background\shell\bash

値にBashを設定

 

フォルダの右クリックメニューにBashが追加されて、ここまでは問題なし。

 

さらに実行するコマンド用のキーを作成。

HKEY_CLASSES_ROOT\Directory\Background\shell\Bash\command

 

値にC:\Ruby26-x64\msys64\msys2.exeを指定 -> 失敗。

いざフォルダで右クリックメニューからBashを選ぶと次のエラーが表示されてBashが開かない。

 

Error: Windows cannot access the specified device, path, or file. You may not have the appropriate permission to access the item

 

参考記事にあったMinttyのコマンドラインを指定して、Bashが起動するようになった。

"C:\Ruby26-x64\msys64\usr\bin\mintty.exe" /bin/bash -l -c "{ cd ""%V""; exec /bin/bash;}"

 

上記の方法だと$HOMEをデフォルトと違う場所しているとき~/.bash_profileが読まれなかった。

msys2_shell.cmd経由で

C:\Ruby26-x64\msys64\msys2_shell.cmd -use-full-path -where "%V"

にしたら解消した。

NFD(Mac由来の濁点が分かれる「が」や「パ」)が入ったフォルダでも大丈夫になった。

「-use-full-path」はWindowsのPATHを強制的に引き継ぐため。

 

参考記事

msysでインストールしたmintty.exeを、ディレクトリ右クリックメニューから起動する - へぬもへメモ