ノートPCからサーバーへ転送中の不完全なファイルがrenameで完成ファイルになる様子

scpアップロード中のファイルはサーバーに存在する — 監視トリガーが未完成ファイルを処理してしまう問題とsupによる対策

Cyberduck や scp、sftp で Linux サーバーへファイルをアップロードするとき、転送が終わるまで対象ディレクトリには何も見えないと思っていた。 でも実際には、アップロード開始直後から転送先にファイルが作られ、そこへ少しずつデータが書き込まれていくことがある。大きなファイルを送ると、サーバー側で ls -lh したときにサイズが増えていく様子が見える。 これ自体は普通の挙動だが、知らないと少し危ない。 たとえば、アップロード先を別のバッチ処理やファイル監視デーモンが見ている場合、まだ途中のファイルを「完成したファイル」として読み込んでしまう可能性がある。jar、画像、CSV、バックアップファイルなど、読み込み側がファイル名だけで判断していると起きやすい。 WinSCP(Windows 向けの SFTP/SCP クライアント)はデフォルトでこの問題を回避している。転送中は内部で一時ファイル名を使い、完了後に正式名へリネームする仕組みが組み込まれているためだ。一方、macOS の Cyberduck は有料課金していてもこの挙動にはなっておらず、普通にアップロードすると転送中から正式名でファイルが見える。 アップロード中のファイルは見える scp や sftp の put は、基本的には転送先のファイルを開いて、そこへデータを書いていく操作だ。 そのため、転送中は次の状態になりうる。 転送完了前のファイルが、不完全なサイズで存在する 転送に失敗すると、中途半端なファイルとして残ることがある 監視処理やバッチ処理が、そのファイルを先に読んでしまうことがある 確認してみる 挙動は、大きめのダミーファイルを送るとすぐ確認できる。 まず手元の Mac などで、500MB のファイルを作る。 dd if=/dev/urandom of=testfile.bin bs=1M count=500 サーバー側では、転送先ディレクトリを監視しておく。 watch -n 0.5 'ls -lh /path/to/target/' 別ターミナルから scp でアップロードする。 scp testfile.bin user@hostname:/path/to/target/ サーバー側の watch で testfile.bin が現れ、サイズが少しずつ増えていけば、転送中のファイルが見えている。 確認が終わったら、ダミーファイルを削除する。 # 手元 rm testfile.bin # サーバー側 rm /path/to/target/testfile.bin supコマンドで安全に転送する 対策の考え方はシンプルで、最初から正式名で置かないことだ。一時ファイル名でアップロードし、完了後にアトミックな mv で正式名に切り替える。 ...

公開: 2026年5月22日 · Toshihiko Arai
1つの.gitをmain、feature A、feature Bの3つのworktreeが共有している図

git worktreeでAI時代の並列開発を試す。Codexに別ブランチを同時に任せるには

AIコーディングエージェントに複数の作業を同時に任せたい場面があります。 たとえば、片方ではUIを直し、もう片方ではテストを直す。あるいは、A案とB案を別々に試す。こういうとき、同じ作業ディレクトリで同時に編集させると、未コミット変更やブランチ切り替え、同じファイルの編集が絡んでかなり危なっかしくなります。 そこで使えるのが git worktree です。 この記事では、1つのローカルリポジトリから複数の作業ディレクトリを作り、feature/new-feature-a と feature/new-feature-b を別々に進める流れを、実際のコマンドと結果で確認します。 git worktree とは git worktree は、1つのGitリポジトリに複数の作業ディレクトリを紐づける機能です。 普通は1つのリポジトリに1つの作業ディレクトリがあり、その中で git switch や git checkout を使ってブランチを切り替えます。 一方、git worktree を使うと、ブランチごとに作業ディレクトリそのものを分けられます。 /tmp/worktree-demo は main /tmp/worktree-demo-a は feature/new-feature-a /tmp/worktree-demo-b は feature/new-feature-b というように、別々の場所で別々のブランチを同時に開けます。 git checkout との違い git checkout や git switch は、今いる作業ディレクトリの中身を別ブランチへ切り替える操作です。 作業途中の変更があると、切り替え時に止められたり、stashやコミットが必要になったりします。 git worktree は、ブランチを切り替えるのではなく、作業ディレクトリを増やします。なので、main の作業場所を残したまま、A用、B用の作業場所を別に用意できます。 AIエージェントに並列で頼む場合は、この差がかなり大きいです。 検証用リポジトリを作る 今回はブログ本体のリポジトリではなく、/tmp に捨てリポジトリを作って試します。 cd /tmp mkdir worktree-demo cd worktree-demo git init -b main printf '# worktree demo\n' > README.md git add README.md git -c user.name='Demo User' -c user.email='[email protected]' commit -m 'initial commit' ここまでで main ブランチに最初のコミットが1つある状態になります。 ...

公開: 2026年4月28日 · Toshihiko Arai