動かざることバグの如し

近づきたいよ 君の理想に

sysctl -p と sysctl --system の違い

環境

  • Ubuntu 24.04

問題

カーネルパラメータを変更したく、 /etc/sysctl.d/配下にの/etc/sysctl.d/99-my.conf に

net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

設定した。しかし sysctl -p しても反映されない。AIに聞いてみたら sysctl -p ではなかった。

誤解してた

結論から言うと、引数なしの sysctl -p/etc/sysctl.conf しか読み込まない。/etc/sysctl.d/ 配下の .conf ファイルは最初から対象外だ。

つまり 99-my.conf に何を書こうが sysctl -p では永遠に反映されない。コメントしか書かれていない実質空の /etc/sysctl.conf を読み直して、何事もなかったかのように終了していただけだった。

正解はこっち。

sudo sysctl --system

読み込む対象の違いはこうなっている。

コマンド 読み込む対象
sysctl -p /etc/sysctl.conf のみ(引数でファイル指定も可)
sysctl -p /etc/sysctl.d/99-my.conf 指定した1ファイルのみ
sysctl --system /etc/sysctl.d//run/sysctl.d//usr/lib/sysctl.d/ などの配下の .conf ファイルを優先順位に従って全部読み込み、最後に /etc/sysctl.conf も反映

ややこしいのは、同じ /etc/sysctl.d/vm.swappiness あたりを置いていると「そっちは効いてるじゃん」となるケース。あれはブート時にsystemdの systemd-sysctl.service/etc/sysctl.d/*.conf を全部読んで適用しているからで、sysctl -p が効いたわけではない。再起動さえ挟めば反映されるので、余計に原因が分かりにくい。

反映されたかどうかの確認

sysctl net.core.rmem_max

sysctl --system は適用したファイルを順に出力してくれるので、パラメータ名のtypoやカーネルモジュール未ロードがあれば sysctl: cannot stat ... のようなエラーがその場で出る。文法チェックも兼ねられて便利。

それでも値が変わらないなら、他のファイルに上書きされている可能性を疑う。

grep -r "rmem_max" /etc/sysctl.d/ /etc/sysctl.conf /etc/ufw/sysctl.conf 2>/dev/null

/etc/sysctl.d/ 内では同じパラメータがあった場合、ファイル名のアルファベット順で後勝ちになる。Ubuntuにはデフォルトで 99-sysctl.conf -> ../sysctl.conf というシンボリックリンクが置かれていて、これは 99-my.conf より後("s" > "m")に処理される。/etc/sysctl.conf 側に同じキーが書いてあれば当然そっちが勝つ。

あとufwを使っているなら /etc/ufw/sysctl.conf も見ておいたほうがいい。こいつが /etc/sysctl.conf の設定を上書きすることがあり、地味に見落としやすい罠になっている。

昔は sysctl -p が正解だと思ってた

10年以上前に触っていたときは sysctl -p で通っていたはずなんだが、と思って調べてみたら、sysctl -p の挙動自体は当時から今まで一切変わっていなかった。変わったのは周辺のエコシステムのほうだった。

  • 設定を /etc/sysctl.d/ に分割して置くやり方が普及した。
    • これはsystemdが持ち込んだ仕組みで、systemd-sysctl.service がブート時に /etc/sysctl.d/*.conf を自動で読み込む。
    • Ubuntuがsystemdを正式採用したのは15.04(2015年)で、それ以前はUpstartやSysV initが主流。
    • 設定は /etc/sysctl.conf に全部書いて sysctl -p で読ませる、という運用がごく普通だった
  • procps側に --system オプションが追加された。
    • それ以前は /etc/sysctl.d/ 配下を手動でまとめて反映させたければ、ファイルを1個ずつ sysctl -p ファイル名 で指定するしかなかった

なので「昔は sysctl -p でよかった」という記憶自体は間違っていない。今でも /etc/sysctl.conf に直書きしている環境なら sysctl -p で問題なく反映される。設定の置き場所だけ今風の /etc/sysctl.d/ に乗り換えておいて、コマンドは昔のまま、というギャップにハマっただけだった。

ちなみに --system の読み込み順は /etc/sysctl.d//run/sysctl.d//usr/lib/sysctl.d/ → ... → 最後に /etc/sysctl.conf となっている。この一覧の最後に /etc/sysctl.conf が居座っているあたり、今でもこいつは「最後に読まれて他を上書きできる」特別な立ち位置を保ち続けているらしい。

参考リンク