ログ日記

作業ログと日記とメモ

2020年のやったことまとめと2021年のやること

2019年〜2020年の前半まではひたすらリニューアルのコードを書いていた。
最終的なサーバーの構成は、いつも通りさくらクラウドPHP、DB、Web Proxyの構成にした。

現状、DockerはCIで使うだけになっている。
重いので今はこれも別のものに変えたくなってきているところ。

systemd-nspawnはテストサーバーで使っている。
結構快適だけれど、コマンド一つでサーバーを増やしたり消したりして柔軟にクラスタを構成するレベルには至っていない。
結局サーバー管理からは逃れられていないのであった。
コンテナを使った場合のセキュリティ更新の仕組みがあまり分かっていない。結局OSのアップデートを毎日確認する昔ながらの運用になった。

サーバー監視もkibanaをやめてcactiに戻した。cactiというかrrdがディスクを食わなくて良いんだよね。



開発PCはMacからLinuxに戻した。
PhotoshopやOffice以外は快適になった。


PHPのプログラムは、テンプレートエンジンをやめたくなってDDDを一部導入したくなって、中途半端に手を付けた状態。
綺麗なコードにできるのはいつだろう。



なんか新しいことをやってみようとしつつ、結局今の規模感だと昔のやり方に戻した方がやりやすいということだった。
あと今まであまり細かく調べてこなかったSEOをやっている。
プログラムやサーバー云々よりも、結局は売上に直結するSEOが重要なので…。


会社の仕事以外には、これもいつも通りちょっとしたサーバー系の設定とかWordPressとかをやった。
ほとんど新しいことはやっていないね。



以前から度々GUIのプログラムを作りたくなったりするんだけれど、手を付けれていない。
今年の目標も…うーん。
なんか趣味のプログラムを書く時間というか気力が減ってきている気がする。
何年も前に作った自分用ツールのプログラムも綺麗にしたいし、手動でやっている定期的な作業も自動化したいし、スマホでメール送信して後でPCでチェックしている作業もアプリか何かでやりたいし、細かいことは色々ある。
今年はそのうちどれかをやろう。

PHPのベンチマークを検証しようとしたらfanが動いてなかった件

https://qiita.com/okdyy75/items/c6f1469ed6a74a075151
https://qiita.com/Maki-Daisuke/items/23c1285500208048de80
これを自分でも検証しようと実行してみた。
PHPがそんなに遅いわけないと思って。

% cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

% docker --version
Docker version 18.09.1, build 4c52b90

% grep 'model name' /proc/cpuinfo |head -n 1
model name      : Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz

% grep processor /proc/cpuinfo |wc -l
12

% free -h
              total        used        free      shared  buff/cache   available
Mem:           31Gi       5.5Gi        19Gi       532Mi       6.3Gi        24Gi
Swap:          31Gi          0B        31Gi

# nvme list
Node             SN                   Model                                    Namespace Usage                      Format           FW Rev  
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1     NY06N091510306P5E    SKHynix_HFS512GD9TNI-L2B0B               1         512.11  GB / 512.11  GB    512   B +  0 B   11710C10
/dev/nvme1n1     50TF30EWF6C1         KXG6AZNV256G TOSHIBA                     1         256.06  GB / 256.06  GB    512   B +  0 B   5107AGLA
git clone https://github.com/okdyy75/bench-docker.git
cd bench-docker/
docker-compose up -d


Go

docker-compose run --rm golang sh -c 'cd go; go build . && ./go'
 ・・(snip)・・
4.8882788 (0x0,0x0)
4.9010998 (0x0,0x0)
4.9262488 (0x0,0x0)
4.9179488 (0x0,0x0)
16.1521789 (0x0,0x0)
51.1434579 (0x0,0x0)
51.2540279 (0x0,0x0)
51.1595889 (0x0,0x0)
51.3981269 (0x0,0x0)
50.5078839 (0x0,0x0)
平均秒数:29.12488324 (0x0,0x0)

Python

docker-compose run --rm python sh -c 'cd python; pip install -r ./requirements.txt && python bench.py'
5.247909
5.105158
5.189029
5.159607
19.598987
44.922379
50.793592
50.576921
50.310744
50.391779
平均秒数:28.729611

PHP

5.5343110561371
4.8346080780029
4.8351881504059
4.7622499465942
4.7532980442047
37.027944087982
49.002175092697
48.619991064072
48.726005077362
48.607387065887
平均秒数:25.670315766335

なんか途中から速度がおかしいね。
Dockerがダメなのかと思ってローカルでそのまま実行したり、PostgreSQLで実行しても同じような傾向になる。
ハードのリソースを使いすぎるとノートパソコンが何らかの制御をしているのか?

2020-12-17 08:06:18.433000
2020-12-17 08:06:18.480800 import CSV start
2020-12-17 08:07:02.661400 import CSV end
2020-12-17 08:07:02.693900 export CSV start
2020-12-17 08:07:02.713000 export CSV end
2020-12-17 08:07:02.713000 compare CSV start
2020-12-17 08:07:02.855700 compare CSV end
2020-12-17 08:07:02.856700
44.423780202866

DBの1万件インサートが遅い。
prepareを一度だけ実行するようにすると少し早くなるけど、8〜9件目ぐらいから結局遅くなる。
ファンが動いてなかったりcpufreqが極端に低くなったりしたので、cpufrequtilsを入れたりthinkfan関連を入れたりした。
ファンは動くようになってcpuクロックも高めにしたけど、やっぱり途中から遅くなる。
少電力系か・・・?
CPUも温度もファンもあまり使ってない段階で遅くなるんだよな。
また今度調べよう。

Debian の LibreOffice が重すぎる件

Debian 10 buster をインストールしてからLibreOfficeが重すぎる。
Calcの計算とかWriterの画像とかじゃなくて、空で立ち上げてメニューを表示するだけでも重い。
PCのスペックは圧倒的に上がったはずなのに、重い。
ちょっと動かすだけでCPUが100%になる。

askubuntu.com
GTK関係?スケーリング解像度の影響だろうか。
Eclipseも動作が不安定だったし。



仕方がないのでDebianLibreOfficeパッケージはapt remove --purge libreoffice* で全て削除して apt autoremove --purge してから
www.libreoffice.org
本家のdebパッケージでバージョン7をインストールした。
めっちゃ軽くなった。

PHPの静的解析 Phan/Psalm/PHPStan の違い

エラーチェックのためにPHPで静的解析ツールをする場合、Phan, Psalm, PHPStan を使えば良いということは検索ですぐ出てくるのだが、どれを使えばいいのか。
それぞれのツールで検知できるものが微妙に異なっているので、全部使うのが安全ではある。

それでも動作の違いや思想の違いを知っておきたいので調べる。

github.com
github.com
github.com

自分がエラーを検知してほしいまたは正しく型チェックしてほしいと思うコードを用意してそれぞれチェックしてみるのが手っ取り早い。
思いつくコードを調べてみた。
設定は基本的に初期のまま。PhanはREADMEにある設定、Psalmはレベル1、PHPStanはレベル8にした。(PsalmとPHPStanで検知レベルの向きが逆である)

<?php
/**
 * @param array<int,string> $arr
 */
function test1(array $arr, ?int $index): ?string
{
    $ret = null;
    if (isset($arr[$index]))
        $ret = $arr[$index];
    return $ret;
}
Phan Psalm PHPStan
PhanTypeMismatchDimFetchNullable エラーなし エラーなし

Phan は配列のインデックスに nullable な値を指定するとエラーになる。

<?php
/**
 * @param array<int,string> $arr
 */
function test1(array $arr): ?string
{
    if (isset($arr[null]))
        return $arr[null];
    return null;
}
Phan Psalm PHPStan
PhanTypeMismatchDimFetchNullable NullArrayOffset エラーなし

こちらはPsalmでもエラー。
PHPの文法的にはOKだが、null は自動的に空文字 '' に変換されるので、PHPStanも正しくはない。



<?php
/** @return mixed */
function test2()
{
    $a = $_GET['a'];
    return $a;
}
Phan Psalm PHPStan
エラーなし MixedAssignment エラーなし

Psalm は mixed の扱いに厳しい。

<?php
function test3(): int
{
    throw new Exception('err');
    return 0;
}
Phan Psalm PHPStan
PhanPluginUnreachableCode エラーなし Unreachable statement

Psalm は未到達コードをチェックしないようである。
https://github.com/vimeo/psalm/issues/403#issuecomment-354441656
オプションを付ければチェックされるようだが、デフォルトではreturnやexitの後のコードはチェックされないようだ。

<?php
/**
 * @template T of DateTimeInterface
 * @param T $d
 * @return T
 */
function test4($d)
{
    $d->format('d');
    return $d;
}
Phan Psalm PHPStan
PhanUndeclaredClassMethod エラーなし エラーなし

Phanはジェネリクスに of が使えないようだ。

<?php
function test4(): void
{
    var_dump(1);
}
Phan Psalm PHPStan
エラーなし ForbiddenCode エラーなし

Psalm は var_dump がエラーする。
エラーを見る限り、危険な関数の使用自体がチェックされるようである。

<?php
/**
 * @template T of DateTime
 * @template U of DateTime
 * @param iterable<T,iterable<string,U>> $dss
 * @param callable(string):int $f
 * @return ?int
 */
function test5($dss, $f)
{
    foreach ($dss as $k => $ds){
        foreach ($ds as $s => $d){
            $diff = $k->diff($d);
            if ($diff->format('%d') == 10)
                return $f($s);
        }
    }
    return null;
}
Phan Psalm PHPStan
PhanUndeclaredClassMethod エラーなし エラーなし

Phan は of が使えないのでエラー。PsalmもPHPStan も入れ子ジェネリクスとコールバック関数の型を理解できる。試しに戻り値の型を ?string にするとエラーになる。

<?php
function test6($a)
{
    echo 'a';
}
Phan Psalm PHPStan
エラーなし MissingParamType, MissingReturnType parameter $a with no typehint specified, no return typehint specified

PHPStanの方がエラーが詳しいような書き方になってしまったがそうではなく、Psalm のようなエラーの型がないだけである。Psalmも詳しいメッセージは出力されている。
Psalm と PHPStan は型が必須のようだ。

<?php
/**
 * @template T
 * @param class-string<T> $c
 * @return T
 */
function test7($c)
{
    return new $c;
}
Phan Psalm PHPStan
エラーなし MixedMethodCall エラーなし

Psalm は mixed に厳しい。コンストラクタの引数が分からないのでnew できるかは不明というのは正しい。

<?php
interface Foo {
    public function bar(string $bar, int $baz): int;
}
class FooImpl implements Foo {
    public function bar(string $_, int $i): int
    {
        return $i++;
    }
}
Phan Psalm PHPStan
PhanParamNameIndicatingUnused ParamNameMismatch エラーなし

PhanとPsalmはパラメーター名が異なればエラー。
今までは単なるコード整形だったけれども、PHP8 で named parameters が来ると意味が変わってくる。

<?php
abstract class P
{
    abstract protected function a(DateTimeImmutable $d): DateTimeInterface;
}
class C extends P
{
    protected function a(DateTimeInterface $d): DateTimeImmutable
    {
        return new DateTimeImmutable($d->format('y-m-d'));
    }
}
Phan Psalm PHPStan
PhanParamSignatureRealMismatchParamType, PhanParamSignatureRealMismatchReturnType MethodSignatureMismatch エラーなし

PHPStanだけPHPの文法に合うようになっている。 (※コメントも参照)
PhanとPsalmはわざとエラーにしている?でもエラーメッセージを見ると共変性と反変性をあえて禁止にしているようには見えない。

<?php
function test8(int $i): bool
{
    switch(true){
    case $i <= 10:
        return true;
        break;
    case $i > 10 && $i <= 20:
        return false;
        break;
    default:
        return true;
        break;
    }
    return true;
}
Phan Psalm PHPStan
PhanPluginUnreachableCode エラーなし Unreachable statement, Comparison operation ">" between int<11, max> and 10 is always true.

Psalm はデッドコードをチェックしない。
PHPStanは、条件10がかぶっていることを見つけてエラーにする。

<?php
function test9(string $s): string
{
    return sprintf('foo%s, %s', $s);
}
Phan Psalm PHPStan
PhanPluginPrintfNonexistentArgument エラーなし Call to sprintf contains 2 placeholders, 1 value given.

PhanとPHPStan はsprintfのフォーマットをチェックする。

<?php
function test9(string $s): string
{
    return sprintf('foo%s, %s', $s, 1);
}
Phan Psalm PHPStan
PhanPluginPrintfIncompatibleArgumentType エラーなし エラーなし

Phanは更に型までチェックする。
PHPStan も実は型をチェックしていて、1をnew DateTimeに変えるとエラーになる。bool|float|int|string|null を受け付けるようだ。



さて、大まかな違いが見えてきた。
Phanは全体的にバランス良くチェックしようとしているが、ジェネリクスの機能が弱い。関数のシグネチャに型がなくてもスルーする。レガシーコードに利用するのに向いていそうだ。
Psalmはmixedに厳しく、全ての型を指定しろという強い意志を感じる。新規プロジェクトに向いている。
PHPStanはPHPが許す文法には寛容に見えるし、mixedをスルーして共変性と反変性を正しく実装しているのは元々のPHPの動作を尊重しているからかもしれない。



※ この記事はQiitaの PHP その2 Advent Calendar 2020 の5日目の記事、今空いてたから登録した。


※ 12/7 追記
コメントをもらったので再チェック。
psalm の使い方が分かってないのかも…。

% ./vendor/bin/psalm --clear-cache
Cache directory deleted
% ./vendor/bin/psalm --version
Psalm 4.2.1@ea9cb72143b77e7520c52fa37290bd8d8bc88fd9
%
% ./vendor/bin/psalm
Scanning files...
Analyzing files...

E

ERROR: MethodSignatureMismatch - src/functions.php:9:5 - Method C::a with return type 'DateTimeImmutable' is different to return type 'DateTimeInterface' of inherited method P::a (see https://psalm.dev/042)
    public function a(DateTimeInterface $d): DateTimeImmutable


ERROR: MethodSignatureMismatch - src/functions.php:9:41 - Argument 1 of C::a has wrong type 'DateTimeInterface', expecting 'DateTimeImmutable' as defined by P::a (see https://psalm.dev/042)
    public function a(DateTimeInterface $d): DateTimeImmutable


------------------------------
2 errors found
------------------------------

Checks took 0.44 seconds and used 57.117MB of memory
Psalm was able to infer types for 100% of the codebase
%
% cat src/functions.php
<?php

abstract class P
{
    abstract public function a(DateTimeImmutable $d): DateTimeInterface;
}
class C extends P
{
    public function a(DateTimeInterface $d): DateTimeImmutable
    {
        return new DateTimeImmutable($d->format('y-m-d'));
    }
}

https://psalm.dev/r/52f57aeabe と結果が異なる。

Linux Kernel 5.8 で Ansible の service, systemd がエラーになる

めっちゃハマった。
別のPCからAnsibleをそのまま持ってきてコンテナに実行したらエラーになった。

RUNNING HANDLER [common : reload nginx] ****************************************************************
 [WARNING]: The service (nginx) is actually an init script but the system is managed by systemd

fatal: [app-php.local]: FAILED! => {"changed": false, "msg": "Service is in unknown state", "status": {}}

ansibleのserviceをsystemdにしてもダメ。
変わったのはカーネルバージョンのみで、OSのバージョンは同じ。
Debianカーネルだけ5.8にしたものでエラーが出た。
カーネル5.8のsystemdのバグらしい。

github.com

コンテナだから中のゲストカーネルも同じ5.8になっちゃうよねえ…。
現段階では、カーネルバージョンを下げるか、少し待って最新版をDLするか、修正を自分で適応させるしかないっぽい。
まだissueのスレッドは進行中。

2日前に回避用の修正はプルリクされたようだ。
github.com

カーネルのバージョン5.7にできれば一番良いんだろうけど、公式パッケージがないとつらい。buster-backports のカーネルって新しいカーネルが出るたびにバージョンアップされるのかな?
5.9になったら直っていることを祈りつつ。
ひとまず、設定が進まないのでパッケージで入れたansibleの /usr/lib/python3/dist-packages/ansible/modules/system/systemd.py を手動修正した。

Debian の KDEデスクトップ設定メモ

gdm3をインストール。
大量に関連パッケージがインストールされるが、気にしないことにした。
セッションはKDE


Alt + Tabのアニメーション
・システム設定 > ディスプレイとモニタ > Compositor > アニメーションの速度
Alt + Tabだけの動作は変えられない?

Alt + Tab のUI
・ウィンドウの操作 > タスクスイッチャー > 選択したウィンドウを表示するの下のアイコンでテーマを選ぶ
 MediumDefault に設定した
  2020/10/29 apt install kwin-addons してからLarge Icons にした

日本語入力

apt install ibus-mozc

MacIME切り替え設定にする。変換/無変換/かな でひらがな <=> カタカナの変換は無し。


konsoleのデフォルトプロファイル設定。

vi .config/konsolerc
[Desktop Entry]
DefaultProfile=default.profile

default というプロファイルを作ったら、このような指定にする。
メニューからの変更や起動時の konsole --profile default では駄目だった。(Ctrl + Shift + N で新しいウィンドウを作ったときに無効になる)
メニューバーをオフにしたあとにオンで立ち上げるには konsole --show-menuba で起動する。
検索すると konsolerc の置き場所が色々出てくるけど、自分の場合(Debian buster)は .config だった。

Debian 10 に Wine 5 をインストール (Photoshopインストールできず)

Debian - WineHQ Wiki
apt の「壊れた変更禁止パッケージ」への対処方法 | marmooo's blog
Winetricks - WineHQ Wiki
Installing Adobe Photoshop on Linux – Linux Hint
Solved: Is it legal to use Photoshop with wine? - Adobe Support Community - 9793726
Wine で WIndows アプリ インストール 設定 - memomuteki


取り敢えず実行したコマンド一覧のメモ。
詳しくはリンク先参照。

dpkg --add-architecture i386

wget -nc https://dl.winehq.org/wine-builds/winehq.key
sudo apt-key add winehq.key

echo "deb https://dl.winehq.org/wine-builds/debian/ buster main" >> /etc/apt/sources.list.d/wine.list

apt update


wget https://download.opensuse.org/repositories/Emulators:/Wine:/Debian/xUbuntu_18.04/amd64/libfaudio0_19.07-0~bionic_amd64.deb
wget https://download.opensuse.org/repositories/Emulators:/Wine:/Debian/xUbuntu_18.04/i386/libfaudio0_19.07-0~bionic_i386.deb
dpkg -i libfaudio0_19.07-0~bionic_amd64.deb
apt install libc-bin
apt --fix-broken install
dpkg -i libfaudio0_19.07-0~bionic_i386.deb
apt install --install-recommends winehq-stable

apt install playonlinux

PlayOnLinuxhttps://www.playonlinux.com/en/download.html 公式のバージョンと同じだったのでaptでインストールした。
PlayOnLinuxの「インストールメニュー」で止まるバグの根本的な解決法 - Qiita
翻訳バグがあるので修正。

apt install gettext
cp /usr/share/locale/ja/LC_MESSAGES/pol.mo .
msgunfmt pol.mo -o fix_pol.po
vi pol.po
msgfmt fix_pol.po -o fix_pol.mo

PlayOnLinuxにwineが表示されないので、再度wineをインストールした。winehq-stableはインストールしなくて良かったかもしれない。というか複数バージョンでややこしくなるから、どちらかに統一した方が良い…?


インストールメニューからAdobe CCをインストールしようとすると、Wine 3.0.3 がインストールされた。先に wine 5 をインストールしていても同じっぽい。どういうことだろう…。


UbuntuにAdobeCCをインストール - Qiita

cd
mkdir bin
cd bin
wget  https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
chmod +x winetricks

./winetricks allfonts
winetricks atmlib gdiplus vcrun2008 vcrun2010 vcrun2012 vcrun2013 vcrun2015 atmlib msxml3 msxml6 gdiplus

vcrun2012、vcrun2015でエラーが出たので、それはスルーで。vcrun2017があったので入れる。
windowsの バージョンを10にする。

wineboot -u

winecfg

古いインストーラhttp://ccmdl.adobe.com/AdobeProducts/KCCC/1/win32/ACCCx4_5_0_331.zip はクラッシュ、自分のWindowsでDLしたインストーラーは"captcha validation has failed"と出てログインできない。インストーラーの起動は出来たんだが。



winehq-staging を入れてバージョンを上げて再度トライ。~/.wine は一旦削除。
そうするとwinetricksでエラーが起きず、古いAcobe CCインストーラーはインストールできた。でも立ち上げるとローディングアイコンがずっとクルクルして進まなかった。


WineHQ - Adobe Photoshop CC 2020 (21.0)
これは無理なのかな。


VMwareWindowsを入れてもいいけど、デュアルブートWindowsが無駄になるんだよなあ…。どうしよ。


追記:
WineHQ Bugzilla – Bug 47015 – Photoshop CC2019 login screen content does not render without native msxml3
最後のコメントに、captchaについて書かれていた。2020-09-22 なので最近の更新?もう少し早く試せば良かったか…。