ブログのリンク切れをチェックするために LinkChecker を使っていて、GitHub Actionsで動かしていますが 最近のバージョンで上手く動かなくなっていたのでなんとか動くように変更した話。
Linkchecker
サイト内のリンクをチェックしてリンク切れを見つけてくれるツール。
開発も未だにアクティブにやってくれているので 使い続けています。
一時期メンテナンスがストップして有志がフォークして開発、みたいな感じだったみたいですが、 現在はlinkcheckerというアカウントのもと運用されています。
contribution guidelines and FAQ · Issue #1 · linkchecker/linkchecker
起こった問題
環境はGitHub Actionsは
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
みたいな感じでやっているもの。 これで入るlinkcheckerは 現在10.1.0です。
ただし、下記のエラーは10.0.0でも10.0.1でも出ます。
9.X系はPython2用なので、Python3にして10.1.0を使おうと思って変えたところエラーが出るようになりました。
Error: Unknown logger type 'html' in 'html' for option '-o, --output'
Linkcheckerでは結果をいろいろな形式で出力することが出来て、-o htmlでHTMLを指定していますが、
このフォーマットは使えない、とのこと。
ただ、フォーマットを指定しないと、デフォルトではtextなんですが、
File "/opt/hostedtoolcache/Python/3.9.13/x64/lib/python3.9/site-packages/linkcheck/configuration/__init__.py", line 225, in logger_new
args = self[loggername]
KeyError: 'text'
なエラーが。
また、コマンドを実行してすぐに、
ERROR: refuse to load module from world writable file '/opt/hostedtoolcache/Python/3.9.13/x64/lib/python3.9/site-packages/linkcheck/logger/graph.py'
ERROR: refuse to load module from world writable file '/opt/hostedtoolcache/Python/3.9.13/x64/lib/python3.9/site-packages/linkcheck/logger/gxml.py'
ERROR: refuse to load module from world writable file '/opt/hostedtoolcache/Python/3.9.13/x64/lib/python3.9/site-packages/linkcheck/logger/html.py'
ERROR: refuse to load module from world writable file '/opt/hostedtoolcache/Python/3.9.13/x64/lib/python3.9/site-packages/linkcheck/logger/sql.py'
...
といったエラーが連発されていました。
これはlinkchecker --helpしてみても出ます。
問題調査
このERRORが出る部分を探してみると、
ここで、
check_writable_by_othersからさらにis_writable_by_othersでチェックが行われてこれが0以外を返しているのが問題っぽい。
check_writable_by_othersにあるos.nameのチェックはGitHub Actions上でもposixということは確認しました。
is_writable_by_othersで、
1 2 3 4 | |
といったことをしてますが、os.statでファイルの状態情報が取れて、stat.ST_MODE(=0)はファイルのパーミッション情報をもつもの。
stat — Interpreting stat() results — Python 3.10.5 documentation
stat.S_IWOTH(=2)のビットに所有者以外に書き込み権限があるかどうか、が入っているとのこと。
なのでこれが0を返せば所有者以外は書き込み権限がなく、所有者以外に書き込み権限があれば2が返ります。
ということで見てみると2が返ってきてました。
普通にlsで見てみると、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
な感じで666でグループ以外の人にも書き込み権限が与えられている状態でした。
これを変えてやれば動くだろうということで、
1 2 3 4 5 6 7 | |
とすると動くようになりました。 logger以外のディレクトリに関してもチェックしてエラーが出ている部分があったので、linkcheck内を全部変更します。
Linkcheckerのモジュール名はlinkcheckでlinkcheckerではないので注意。
なぞ
ここ とかを見るとこの辺のチェックはずいぶん前からあったようです。
まず最初になぜこのチェックが必要なのか、というのがよくわかってません。 ファイルが下手な変更されていると困るというのはわかりますが、 他のモジュールとかも全部しないと意味ないような?
一方で、pipで入れたもののpermissionがなぜ666になっているのか?
actions/setup-python
がよしなに用意してくれているもので、実行ユーザーのrunnerが直接
pip installで入れられるsite-packagesディレクトリを用意してくれていますが、
その中にファイルを作ると全て他人にも書き込み権限が与えられてしまう仕様なのか
pipの仕様なのか。。。
ちょっと見てみると、
(わかりやすく$ 付けてますがそれぞれのコマンドをGitHub Actions上でrunで実行した結果)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
という感じで、umaskは一般的な0022ですが、/optのdefault ACLがotherにもrwxになってます。
Pythonのパッケージが入るsite-packagesもowner/groupは違いますが全てrwx。
ということで、この権限状態が問題なようです。
/optも通常のLinuxだと
1 2 3 | |
だとは思いますが、GitHub Actionsで用意されているUbuntuでは最初から(setup-pythonやcheckoutなどを行う前に見ても)この状態でした。
通常はコンテナ的な使い方するだけならこの状態の方が便利といえば便利なわけですが、 Linkcheckerでなくとも、ファイルの権限を気にするツールは他にもあるので、 ちょっとこの仕様は覚えておいた方が良いな、と。
