動かざることバグの如し

近づきたいよ 君の理想に

PulseAudioを使って別のLinuxサーバーのスピーカーから音を再生したい

環境

やりたいこと

サーバーAとBがある。サーバーAにはtest.wavがあり、サーバーBにスピーカーがある。

サーバーAから aplay test.wavを実行し、サーバーBのスピーカーから音を鳴らしたい。

今回はPulseAudioを使って実現してみる。

  • サーバーB: PulseAudioサーバー
  • サーバーA: PulseAudioクライアント

サーバー側の設定

echo 'load-module module-native-protocol-tcp listen=0.0.0.0 auth-anonymous=1' > /etc/pulse/default.pa.d/my.pa

設定反映

$ systemctl --user restart pulseaudio.service $ systemctl --user restart pulseaudio.socket

sshすると自動で起動するが、再起動後に反応しなくなってしまうので自動起動するようにしておく

$ systemctl --user enable pulseaudio Created symlink /home/thr3a/.config/systemd/user/default.target.wants/pulseaudio.service → /usr/lib/systemd/user/pulseaudio.service. Created symlink /home/thr3a/.config/systemd/user/sockets.target.wants/pulseaudio.socket → /usr/lib/systemd/user/pulseaudio.socket.

# クライアント側の設定

設定前に確認

$ pacmd list-sinks 1 sink(s) available. * index: 0 name: <auto_null> driver: <module-null-sink.c> flags: DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY state: IDLE suspend cause: (none) priority: 1000 volume: front-left: 65536 / 100% / 0.00 dB, front-right: 65536 / 100% / 0.00 dB balance 0.00 base volume: 65536 / 100% / 0.00 dB volume steps: 65537 muted: no current latency: 2045.22 ms max request: 375 KiB max rewind: 375 KiB monitor source: 0 sample spec: s16le 2ch 48000Hz channel map: front-left,front-right Stereo used by: 0 linked by: 0 configured latency: 2000.00 ms; range is 0.50 .. 2000.00 ms module: 13 properties: device.description = "Dummy Output" device.class = "abstract" device.icon_name = "audio-card"

設定

pacmd load-module module-tunnel-sink server=192.168.16.16

いざ確認 問題なければこれでサーバーBから音が鳴る

aplay /tmp/test.wav

# 設定の永続化

ただこれだと毎回設定しなくちゃいけなくて面倒

/etc/pulse/client.conf.d/my.conf 作成して以下

default-server = 192.168.16.16

確認

$ pacmd list-sinks 1 sink(s) available. * index: 24 name: <tunnel-sink.192.168.16.16> driver: <module-tunnel.c> flags: NETWORK HW_MUTE_CTRL HW_VOLUME_CTRL LATENCY state: SUSPENDED suspend cause: IDLE priority: 0 volume: front-left: 65536 / 100%, front-right: 65536 / 100% balance 0.00 base volume: 65536 / 100% volume steps: 65537 muted: no current latency: 0.00 ms max request: 0 KiB max rewind: 0 KiB monitor source: 24 sample spec: s16le 2ch 44100Hz channel map: front-left,front-right Stereo used by: 0 linked by: 0 fixed latency: 250.00 ms module: 47 properties: device.description = "USB Audio and HID Analog Stereo on thr3a@NuxBox" tunnel.remote.server = "192.168.16.16" device.icon_name = "audio-card" tunnel.remote_version = "35" tunnel.remote.user = "thr3a" tunnel.remote.fqdn = "NuxBox" tunnel.remote.description = "USB Audio and HID Analog Stereo"

# 参考リンク

- [PulseAudio - ArchWiki](https://wiki.archlinux.jp/index.php/PulseAudio)
- [Linux同士でオーディオを転送する - mattintosh note](https://mattintosh-note.jp/entry/20160202/1454395624)

JavaScriptでパスワード生成するときはMath.random()を使うな

パスワード生成するメソッド

指定した桁数のパスワードを生成するメソッドをTypeScriptで実装した。

別にjsでも動くと思う

export const generatePassword = (length: number): string => {
  const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
  let password = '';
  for (let i = 0; i < length; i++) {
    const randomIndex = Math.floor(Math.random() * characters.length);
    password += characters[randomIndex];
  }
  return password;
};

console.log(generatePassword(8));

動作としては問題ないのだが、何回か実行しているとどうも同じ文字が連続して生成される気がする。

❯ bun index.ts
2xdd87lv
❯ bun index.ts
qeezy2ew

でChatGPTに聞いたら案の定 Math.random()を使うのは良くないらしい

代わりにCrypto.getRandomValues()使えと言われたので書き直してもらった

export const generatePassword = (length: number): string => {
  const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
  let password = '';
  const randomValues = new Uint32Array(length);
  crypto.getRandomValues(randomValues);
  for (let i = 0; i < length; i++) {
    const randomIndex = randomValues[i] % characters.length;
    password += characters[randomIndex];
  }
  return password;
};
  • const randomValues = new Uint32Array(length);
    • Uint32Arrayは、符号なし32ビット整数の配列を作成します。
    • lengthは配列の長さで、ここではパスワードの長さに相当します。
    • この行は、ランダムな値を格納するための空の配列を作成します。
  • crypto.getRandomValues(randomValues);
    • cryptoは、暗号化操作のためのグローバルオブジェクトです。
    • getRandomValuesメソッドは、引数として渡された配列を、暗号学的に安全なランダムな値で埋めます。
    • この行は、randomValues配列をランダムな数値で満たすために使用されます。

よさそう

❯ bun index.ts
n4je65la

てかググってたらもっとスマートに実装してる人いたわ

export const generatePassword = (length: number): string => {
  const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
  return Array.from(crypto.getRandomValues(new Uint32Array(length)))
    .map(value => characters[value % characters.length])
    .join('');
};

参考リンク

Dockerで標準出力にログ吐くsquid

環境

やりたいこと

かつてDockerでsquid実装した記事書いた

dockerでsquidプロキシサーバーを構築する - 動かざることバグの如し

あれから5年色々変わって動かなくなってたので再実装

FROM ubuntu:24.04

ENV TZ=Asia/Tokyo
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && \
    apt-get install -y squid && \
    rm -rf /var/lib/apt/lists/*

squid.conf

logfile_rotate 0
cache_log stdio:/dev/tty
access_log stdio:/dev/tty
cache_store_log none
# cache_store_log stdio:/dev/tty

で必ずdocker-compose.yml起動時には ttyをtrueにする必要がある。

command: squid -N
tty: true

実際に動かすのは https://github.com/thr3a/docker-build-station/tree/master/squid 参照

Nextjsで複数台にデプロイするとJSが404エラーになる問題

環境

  • Nextjs 14

Nextjs複数台に同時にデプロイできない問題

Nextjsを使用している際に、複数のサーバーに同時にデプロイしようとすると問題が発生することがある。

具体的には、ビルドIDが各サーバーで異なるため、JSのURLが変わってしまう。よってブラウザを何回かリロードしているとJSが404でエラーになる。

これは、NextjsがデフォルトでランダムなビルドIDを生成するためであり、複数のサーバー間でビルドIDを統一しないと、クライアントサイドでのキャッシュの不整合など、予期せぬ問題が発生することがある。

この問題は、特に大規模なアプリケーションや高可用性を求める環境で顕著になり、デプロイの効率性やアプリケーションの安定性に影響を与える。

解決策

next.config.jsに以下のようにgenerateBuildIdを追記する。いわゆるhashシード的なもので、ここでは「my-build-id」と固定の文字列だが運用する場合はgitハッシュがベストだろう。

module.exports = {
  generateBuildId: async () => {
    // You can, for example, get the latest git commit hash here
    return 'my-build-id'
  },
}

参考リンク