LinuxのユーザーUIDは、usermod -u 新しいUID ユーザー名で変更できます。ただし、アカウントの番号を変えるだけでは移行は完了しません。旧UIDのまま残るファイル、ACL、実行中のプロセスなどを確認する必要があります。
本記事では、単一ホストでローカル管理している一般ユーザー1名を対象に、変更前の調査から所有者の移行、変更後の確認までを説明します。コマンドはBash、shadow-utilsのusermod、GNU Findutils/Coreutilsを前提とします。例のユーザー名・番号・パスは、そのまま実行せず実環境で確認した値に置き換えてください。
UID変更で最初に確認すること
UIDを別の番号にするだけで、セキュリティが強化されるわけではありません。移行先とのID統一など、変更する理由と影響範囲が明確な場合に行います。UIDは秘密情報ではなく、認証や権限設定の代わりにもなりません。
- 対象ユーザーとは別の管理者アカウントで作業し、復旧用の管理者セッションを確保する。対象ユーザーから
sudoしたシェルで、そのユーザー自身のUIDを変更しない。 - 旧UID、変更先UID、ホーム、所属グループ、データ保存先を記録する。旧UIDは必ず
usermodの実行前に取得する。 - 新UIDを使用するアカウントだけでなく、その番号を所有者やACLに持つ既存データがないか確認する。
- 対象ユーザーの全セッションと関連ジョブを停止し、作業中に再ログイン・自動起動・ファイル変更が起きない状態にする。
- 所有者・グループ・権限・ACL・拡張属性などを復元できるバックアップと復旧手順を準備する。
root(UID 0)、OSやサービスが管理するシステムアカウント、LDAP/AD/NIS/SSSDなどの集中管理アカウント、NFS等の共有ストレージ、コンテナやユーザー名前空間、IDマッピングを使う環境には、この手順をそのまま適用しないでください。管理元やストレージ側を含めた別の移行計画が必要です。複数アカウントが既に同じUIDを共有している場合も、所有ファイルを番号だけで振り分けられないため、本記事の手順では進めません。
UIDとGIDの違い、usermodで変わる範囲
UIDはユーザーを、GIDはグループを識別する番号です。ファイルには所有者UIDと所有グループGIDが別々に記録されます。ユーザー名とグループ名が同じでも、UIDとGIDを同じ値にそろえる必要はありません。
usermod -uで変更するのはユーザーのUIDです。GIDをついでに変更したり、所有者変更でユーザー:グループを一律指定したりしないでください。共有ファイルなどに意図的に設定されたグループが変わるおそれがあります。
shadow-utilsのusermodマニュアルでは、対象ユーザーのメールボックスと、ホーム内でそのユーザーが所有するファイルは自動更新の対象とされています。一方、ホーム外の所有ファイルは手動対応が必要です。また、ホーム自体の所有者が旧UID・新UIDのどちらでもない場合、ホーム内の自動更新は行われません。すべての所有ファイルが自動で移行する、と考えないでください。実際の挙動はインストール済みのman usermodでも確認します。
手順1:対象アカウントと旧UIDを記録する
以下は、exampleuserの変更先候補を2001とする例です。2001が空いていることを保証する例ではありません。以降のコマンドは同じ管理者シェルで順に確認し、途中で失敗した場合は先へ進まないでください。
account='exampleuser'
new_uid='2001'
getent passwd "$account"
awk -F: -v name="$account" '$1 == name { print }' /etc/passwd
id "$account"
old_uid=$(id -u -- "$account")
printf 'account=%s old_uid=%s new_uid=%s\n' "$account" "$old_uid" "$new_uid"/etc/passwdに対象のローカルエントリーが1件あり、getentやidの結果とUID・ホーム等が一致することを確認します。名前解決の管理方式が不明、結果が食い違う、旧UIDが取得できない、旧UIDが0の場合は中止します。旧UIDと新UIDが同じなら、UID変更は不要です。記録はシェル変数だけに頼らず、作業記録にも残してください。
一般ユーザーのUID範囲は、ディストリビューションと組織の運用で異なります。/etc/login.defsのUID_MIN・UID_MAX等と管理方針を確認します。usermod -uはこれらの範囲を自動チェックしないため、「コマンドが受理したから適切な番号」とは判断できません。
手順2:新UIDの衝突とデータの所在を調べる
アカウントの重複を確認する
getent passwd "$new_uid"
awk -F: -v uid="$new_uid" '$3 == uid { print }' /etc/passwd
awk -F: -v uid="$old_uid" '$3 == uid { print }' /etc/passwd新UIDの照会で別のアカウントが表示されたら、その番号は使用しません。旧UID側も、対象以外のアカウントと共有していないことを確認します。getentで何も表示されないことだけでは、未使用と断定できません。NSSの設定や参照先が正常であることを確認し、集中管理との競合が疑われる場合は管理元に確認してから判断します。重複を許すusermod -oで回避しないでください。
調査するローカル領域を決める
対象ユーザーのホーム、ホーム外の個人データ、メールボックス、ジョブの保存先などを洗い出します。未接続ディスク、バックアップから復元予定のデータ、アプリケーション内の数値UIDも確認対象です。調査漏れがあるまま旧UIDを別ユーザーへ再割り当てすると、残ったデータへのアクセスにつながるおそれがあります。
新UIDの調査は、旧UIDのファイルがある場所だけに限定しません。他ユーザーのホームや共有ディレクトリを含め、新UIDでアクセス可能になり得るローカル領域とACLも調べます。調査範囲を網羅できない場合は、未使用という判定を保留してください。読み取り調査の範囲と所有者を変更する範囲は別に決め、調べた領域をすべて変更対象にしないでください。
以下のscopeは、調査・変更を承認したローカルディレクトリ1か所を指定する例です。実在する絶対パスに置き換え、パスの途中も含めてシンボリックリンクではないこと、対象外のサブマウントがないことを事前に確認してください。ホームとホーム外の領域はそれぞれ確認し、対象外のシステム領域まで広げないでください。
scope='/srv/exampleuser'
# 旧UIDの所有ファイルを調べる(表示のみ)
sudo find -P "$scope" -xdev -uid "$old_uid" -ls
# 新UIDを既に所有者に持つファイルを調べる(表示のみ)
sudo find -P "$scope" -xdev -uid "$new_uid" -lsGNU findの-uidは数値UIDを条件にします。アカウントが削除済みでもファイルの数値UIDは残るため、新UIDのファイルが見つかったら、その由来と正しい所有者を確認するまで変更しません。ACLに新UIDが登録されていれば、アカウントを割り当てただけでその権限が有効になり得る点も調べます。
-Pは探索中のシンボリックリンクをたどらず、-xdevは別ファイルシステムのディレクトリへ降りることを抑えます。ただし、-xdevは完全な境界保護ではありません。マウントポイント自体は評価対象になり得て、同じデバイス上のbind mountも単純には除外できません。開始点がNFSなら、そのNFSを探索してしまいます。本例はローカル領域とマウント構成を確認済みの場合に限ります。別ディスクは個別に調査し、未調査部分を「該当なし」と扱わないでください。
表示結果だけでなく、終了状態とエラー出力も確認してください。権限不足、I/Oエラー、未マウントなどがあれば調査は未完了です。2>/dev/nullでエラーを隠さないでください。ファイル一覧を機械処理する場合は改行を含む名前も想定し、-print0等のNUL区切りを使います。表示用一覧をそのままシェルコマンドとして実行してはいけません。
手順3:バックアップと停止状態を確保する
内容だけでなくメタデータを保全する
- アカウント設定と変更前のUID・GID対応を、管理者だけが読める場所に保管する。パスワード情報を含む設定のバックアップは特に厳重に扱う。
- 対象ファイルの内容に加え、数値UID/GID、通常のモード、setuid/setgid、アクセスACL・デフォルトACL、拡張属性、必要なセキュリティラベルやファイルケーパビリティを記録・保全する。
- 使用するバックアップ方式が必要なメタデータを保存・復元できることを、別の検証環境で確認する。単純なコピーだけで十分と決めつけない。
- ホーム内も含め、自動変更される範囲をバックアップする。外部マウントや他者のデータをホーム配下に含む構成は、本例のまま進めない。
Linuxでは所有者変更に伴ってsetuid/setgidビットやファイルケーパビリティが消える場合があります。これはchown(2)の仕様に関わるため、後からUIDを戻すだけでは元の状態に戻りません。特権ビットやケーパビリティは、必要性を確認せず一括で付け直さないでください。
別の管理者セッションから対象ユーザーを停止する
対象ユーザーをログアウトさせ、SSH・デスクトップ・端末多重化ツールのセッション、ユーザーサービス、cron/atジョブなど、そのUIDで処理を再開する経路を確認します。作業時間中は新しいログインや自動起動を管理手順に従って止め、対象データをほかのユーザーやプロセスが書き換えない状態にします。パスワードロックだけでは、公開鍵によるログイン等をすべて止められるとは限りません。
# procps-ng pgrepでの確認例(読み取りのみ)
# 実UIDが旧UIDのプロセス
sudo pgrep -l -U "$old_uid"
# 実効UIDが旧UIDのプロセス
sudo pgrep -l -u "$old_uid"pgrepの-Uは実UID、-uは実効UIDの条件です。該当があれば、その処理を特定して正常終了させます。終了状態1は該当なし、2・3はエラーなので区別してください。この確認は保存UID・ファイルシステムUIDや、確認直後の再起動を網羅するものではありません。プロセスや書き込みを確実に停止できない場合は、保守用のオフライン環境など、管理者が安全に停止状態を確保できる方法を選びます。
対象ユーザーのプロセスが残る状態ではusermodを実行しません。「使用中」と拒否された場合も、プロセス確認を省略したり、アカウントファイルを直接書き換えたりして回避しないでください。
手順4:アカウントのUIDを変更する
バックアップ、未使用UID、ローカルアカウント、停止状態をすべて再確認したうえで実行します。これは実際にアカウントと一部ファイルの所有者を変更する操作です。
sudo usermod --uid "${new_uid:?新UIDが未設定です}" -- "${account:?対象ユーザーが未設定です}"終了状態とメッセージを確認した後、アカウントが新UIDになっていることを読み直します。old_uidは変更前の値として保持し、ここでid -uの結果を代入し直さないでください。
getent passwd "$account"
id "$account"
printf '変更前UID=%s / 変更先UID=%s\n' "$old_uid" "$new_uid"失敗・中断・予想外の結果があった場合、アカウントとホームの一部だけが変わっている可能性も考慮し、記録と現在の状態を照合します。原因が不明なまま次の所有者変更へ進んだり、同じ操作を繰り返したりしないでください。
手順5:確認済みの領域で旧UIDの所有ファイルを移す
まず、手順2と同じ領域で旧UIDの残存を再確認します。ホーム内で自動更新済みのファイルは旧UIDの検索には出てきません。ホーム外だけでなく、ホーム・メールボックスの結果も確認対象です。
sudo find -P "${scope:?対象パスが未設定です}" -xdev \
-uid "${old_uid:?旧UIDが未設定です}" -ls表示されたファイルが本当に移行対象であることを確認してから、その領域に限って変更します。scopeは/にせず、あらかじめ調査したパスを1か所ずつ扱ってください。空でないだけでは安全なパスとは限りません。以下の変数チェックは入力漏れ防止であり、範囲の承認やUIDの妥当性確認を代行するものではありません。
sudo find -P "${scope:?対象パスが未設定です}" -xdev \
-uid "${old_uid:?旧UIDが未設定です}" \
-exec chown -h --from="+${old_uid}" \
"+${new_uid:?新UIDが未設定です}" -- {} +この例では、find -uidで旧UIDを選び、chown --fromで変更直前の所有者も限定します。-hはシンボリックリンクの参照先ではなくリンク自体を扱います。新しい所有者だけを指定し、コロンやグループを付けないため、所有グループは変更しません。仕様はGNU chownのマニュアルを参照してください。
+数値は、GNU chownで数値UIDとして解釈させる指定です。数字だけのユーザー名が存在する場合との混同を避けます。この指定はchown側だけに用い、find -uidには付けません。find -uid +1001はUID 1001そのものではなく、1001より大きい範囲を表すためです。
この組み合わせでも競合状態を完全には防げません。検索後に親ディレクトリやファイルが差し替われば、想定外の対象に作用する余地があります。--fromや-hを付けたから稼働中の共有領域で安全に実行できる、という意味ではありません。停止状態を維持できない場合は実行しないでください。GNU Findutilsの安全性に関する説明も確認します。
同じinodeへのハードリンクは所有者情報を共有します。確認したパスの外に別名がある場合、その別名から見える所有者も変わります。共有データや複数リンクを持つファイルの影響範囲も事前に確認してください。また、この処理は一括トランザクションではありません。途中のエラーは一部成功を意味し得るため、出力と終了状態を記録し、残存ファイルを再調査します。
手順6:ACL・ジョブ・アプリケーション設定を個別に確認する
名前付きACLは所有者変更と分けて扱う
ACLのuser::はファイル所有者の権限ですが、user:1001:r--のような名前付きユーザーACLは、指定されたUIDへの権限です。chownでファイル所有者を移しても、旧UIDを指定する名前付きエントリーまで一括移行したことにはなりません。ディレクトリのデフォルトACLも確認します。
# 調査済みのファイルまたはディレクトリ1件のACLを数値で表示
sudo getfacl -n -p -- /srv/exampleuser/report.txtACLを使用している領域は、対象ユーザーが所有していないファイルも調べます。旧UID・新UIDのエントリー、アクセスACL・デフォルトACL、マスクと実効権限を記録し、元の権限を維持する移行を個別に設計してください。確認せず新UIDへrwxを付け足すと、過剰な権限付与や旧UIDの権限残存につながります。ACLの構造とgetfaclの数値表示は、ACLプロジェクトのマニュアルを参照してください。
ファイル所有者以外の依存関係を確認する
- cron・at:ジョブ内容だけでなく保存ファイルの所有者や再登録方法を、使用中の実装に従って確認する。usermodが自動修正するものと考えない。
- サービス・アプリケーション:数値UIDを直接設定する箇所、キャッシュ、ソケット、ログ、クォータなどの依存関係を調べる。ユーザー名参照と数値参照を区別する。
- 権限メタデータ:所有グループ、通常の権限、ACL、拡張属性、特権ビット・ケーパビリティを変更前の記録と照合する。
- 保存済みデータ:取り外したディスクや古いバックアップを後から戻すと旧UIDが再登場し得るため、復元時の扱いも記録する。
手順7:変更後の確認と利用再開
対象ユーザーを再ログインさせる前に、各調査領域の所有者とメタデータを確認します。新UIDのファイルが存在することだけでは十分ではありません。旧UIDの残存がないか、必要なデータだけが移ったか、グループや権限が意図せず変わっていないかを照合してください。
id "$account"
# 調査済みの領域ごとに旧UIDの残存を確認
sudo find -P "$scope" -xdev -uid "$old_uid" -ls
# ホームと代表的なデータの数値UID/GID・権限を確認
ls -ldn -- /home/exampleuser /srv/exampleuser
ls -ln -- /srv/exampleuser/report.txt- ファイル調査がエラーなく完了し、旧UIDの残存・ACL・メタデータの差分を説明できる状態にする。残す必要があるデータは理由を記録する。
- 停止したジョブや関連サービスを、確認したものから再開する。ログの場所はディストリビューションやサービスによって異なるため、対象のログでエラーを確認する。
- 対象ユーザーで新しいログインセッションを作成し、引数なしの
idで実際のセッションUIDを確認する。管理者側のid ユーザー名だけで済ませない。 - テスト用ファイルの作成・読み書き、必要な共有データへのアクセスを確認する。アクセスできるべきでないデータに権限が増えていないことも確認する。
- 復旧用管理者セッションは、ログインと業務上必要な動作の確認が終わるまで維持する。
UID変更のためにOS再起動が常に必要なわけではありません。既存プロセスの資格情報が自動で新UIDへ置き換わるわけでもないため、事前に処理を止め、変更後は新しいログインや関連プロセスの起動で確認します。環境の事情で再起動を選ぶ場合もありますが、再起動は残存ファイルやACLを修復する操作ではありません。
失敗した場合と、複数ユーザーを変更する場合
戻す前に現在の状態を調べる
問題が起きたら利用再開を止め、アカウントのUID、旧UID・新UIDのファイル、ACL、作業ログを照合します。UIDを元の番号へ戻すだけでは、変更済みファイルや失われた権限メタデータは復元されません。変更後に作られたファイルも考慮し、検証済みのバックアップと復旧手順を使います。
新UIDのファイルをすべて旧UIDへ戻す逆向きの一括処理は避けてください。移行前から存在したデータや変更後に作成されたデータを区別できず、別の所有者のファイルまで巻き込む可能性があります。
複数ユーザーの一括ループをそのまま実行しない
複数ユーザーのUID交換は、1人ずつの変更を単純なループにしても解決しません。例えばAの変更先がBの現在のUIDなら、その時点で衝突します。重複を強制するとファイルの帰属を区別しにくくなり、処理途中で失敗した場合の復旧も複雑です。
一括移行では、全ユーザーの旧→新UID対応、変更先の衝突、孤立したファイルやACL、必要な一時UID、処理順序、停止範囲、検証・復旧の単位を先に設計します。本記事では、未検証の一括変更スクリプトは提示しません。練習する場合も、本番データを持たない使い捨てVM等で行い、ホストのアカウントや共有ストレージを対象にしないでください。
よくある質問
UIDと同じ番号にするためにGIDも変更すべきですか?
いいえ。UIDとGIDは別の識別子で、数値をそろえる義務はありません。GID変更が必要なら別途計画します。shadow-utilsのgroupmodマニュアルでも、旧GIDのファイルのグループ所有者は手動修正が必要とされています。共有グループの場合は他ユーザーにも影響します。
新UIDがgetentに出なければ使えますか?
それだけでは決められません。名前解決元の正常性、ローカル設定、管理上の予約に加え、新UIDを所有者・名前付きACLに持つ残存データを調べます。未接続の媒体や将来復元するバックアップも考慮します。
ホームを再帰的にchownすれば十分ですか?
十分ではありません。ホーム外のデータやACLが残る可能性があり、条件なしの再帰的chownはホーム内のroot所有ファイルや共有グループの設定などを壊しかねません。旧UIDで対象を選び、調査済みの範囲だけを扱います。
まとめ
LinuxのUID変更は、アカウントの番号変更と、数値UIDに依存するデータの移行を分けて考えることが重要です。別の管理者セッション、旧UIDの記録、衝突調査、復元可能なバックアップ、プロセスと書き込みの停止を先に整えます。
そのうえでusermod -uを実行し、確認済みのローカル領域に限って旧UIDの所有ファイルを移行します。GIDを不用意に変えず、ACL・ジョブ・権限メタデータを別途確認し、新しいログインで動作を検証してから利用を再開してください。


コメント