ブログのリンク切れをチェックするために 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でなくとも、ファイルの権限を気にするツールは他にもあるので、 ちょっとこの仕様は覚えておいた方が良いな、と。