第16章 ユーザー管理とジョブスケジューリング
LPIC-1 107.1 / 107.2 相当
複数人で使うことを前提としたLinuxならではの、ユーザー・グループ管理の仕組みと、処理を自動的に実行するスケジューリングの方法を扱います。
ユーザー・グループ管理コマンド
| コマンド | 役割 |
|---|---|
useradd ユーザー名 | 新規ユーザーを作成 |
usermod | 既存ユーザーの設定を変更 |
userdel | ユーザーを削除 |
passwd ユーザー名 | パスワードを設定・変更 |
groupadd グループ名 | 新規グループを作成 |
$ sudo useradd -m -s /bin/bash alice # -m: ホームディレクトリ作成, -s: 既定シェル指定(正常時は無出力)
$ sudo passwd alice
New password: (入力しても画面には表示されない)
Retype new password:
passwd: password updated successfully
$ sudo usermod -aG staff alice # -aG: 既存グループを維持したままstaffに追加(正常時は無出力)
$ sudo usermod -L alice # -L: アカウントをロック(ログイン不可に。正常時は無出力)
$ sudo usermod -U alice # -U: ロックを解除(正常時は無出力)
$ id alice # aliceのUID・GID・所属グループを確認
uid=1001(alice) gid=1001(alice) groups=1001(alice),1002(staff)
この行のこの値に注目: passwdはパスワードを画面に表示せず2回入力させ、成功するとpassword updated successfullyと表示します。useradd/usermodはいずれも成功時に無出力なので、変更が反映されたかどうかは最後のid aliceのように別コマンドで確認するのが基本です。
usermod -G staff aliceのように-aを付け忘れると、aliceの所属グループが「staffだけ」に上書きされ、それまで所属していた他のグループから外れてしまいます。既存のグループを維持したまま追加したい場合は必ず-aG(append + group)とセットで使いましょう。
ユーザー情報を保持するファイル
| ファイル | 内容 |
|---|---|
/etc/passwd | ユーザー名・UID・GID・ホームディレクトリ・既定シェルなど(パスワード本体は含まれない) |
/etc/shadow | 暗号化されたパスワードと有効期限情報。root以外は読めない |
/etc/group | グループ名とそのメンバー一覧 |
/etc/gshadow | グループのパスワード情報(グループパスワード機能を使う場合) |
/etc/passwdの各行は:区切りで7つのフィールドを持ちます。例えばalice:x:1001:1001:Alice:/home/alice:/bin/bashという行は、ユーザー名・パスワード欄(実体は/etc/shadowにあるため慣習的にxと表記)・UID・GID・コメント欄・ホームディレクトリ・既定シェルの順です。UID 0は常にrootに割り当てられ、多くのディストリビューションではUID 1〜999程度をシステムアカウント用、それ以降を一般ユーザー用に区分けする慣習があります。
cron — 定期的にコマンドを実行する
crontab -e でユーザーごとのスケジュールを編集します。書式は「分 時 日 月 曜日 コマンド」の5つの数値(または *)です。
# 分 時 日 月 曜日 コマンド
0 3 * * * /home/user/backup.sh # 毎日午前3時に実行
*/15 * * * * /usr/local/bin/check.sh # 15分おきに実行
0 9 * * 1 /home/user/weekly-report.sh # 毎週月曜9時に実行(曜日: 0=日曜)
0 0 1 * * /home/user/monthly.sh # 毎月1日の午前0時に実行
30 8 * * 1-5 /home/user/weekday-check.sh # 月〜金(平日)の8時30分に実行。ハイフンで範囲指定
$ crontab -l # 現在のcron設定を確認
0 3 * * * /home/user/backup.sh
*/15 * * * * /usr/local/bin/check.sh
$ crontab -e # 編集(エディタが開くだけで、保存終了時以外は無出力)
$ crontab -r # 自分のcrontab設定をすべて削除(確認なしなので要注意。正常時は無出力)
$ crontab -l
no crontab for user
この行のこの値に注目: crontab -lは登録済みのcron行をそのまま表示するので、書式ミスがないかをここで目視確認できます。crontab -rは確認なしで即削除するコマンドで、削除後に再度crontab -lを実行するとno crontab for userと表示され、設定が空になったことが分かります。
各フィールドでは、*(すべての値)、,(複数の値を列挙。例: 1,15は1日と15日)、-(範囲指定)、/(間隔指定)を組み合わせて柔軟なスケジュールを表現できます。cronジョブの標準出力・標準エラー出力は、既定ではそのユーザー宛のメールとして送信される点も覚えておくとよいでしょう(メール転送が設定されていない環境では実質破棄されることも多いです)。出力を破棄したい場合は明示的に > /dev/null 2>&1 をコマンドの末尾に付けます。
at — 1回だけ指定時刻に実行する
cronが「繰り返し」の予約なのに対し、at は「1回だけ」の予約に向いています。
$ at 22:00
warning: commands will be executed using /bin/sh
at> /home/user/shutdown-check.sh
at> Ctrl+D で確定
job 3 at Sat Aug 22 22:00:00 2026
$ at now + 30 minutes # 相対時間での指定も可能
warning: commands will be executed using /bin/sh
at> /home/user/check-disk.sh
at> Ctrl+D で確定
job 4 at Fri Aug 21 15:07:00 2026
$ at 09:00 tomorrow # 翌日の時刻を指定
warning: commands will be executed using /bin/sh
at> /home/user/weekly-report.sh
at> Ctrl+D で確定
job 5 at Sat Aug 22 09:00:00 2026
$ atq # 予約済みジョブの一覧を確認
3 Sat Aug 22 22:00:00 2026 a alice
4 Fri Aug 21 15:07:00 2026 a alice
5 Sat Aug 22 09:00:00 2026 a alice
この行のこの値に注目: atはコマンドを確定するとその場でjob N at 日時という行を返し、これがジョブ番号と実行予定時刻の確定通知になります。予約した内容を後から確認したいときはatq(at -lと同等)でキュー内のジョブ一覧を一覧表示します。
システム全体のcron設定と/etc/skel
個人のcrontab以外にも、システム全体で使われるスケジュール設定があります。
| 場所 | 役割 |
|---|---|
/etc/crontab | システム全体のcrontab。実行ユーザー名を指定する列がある点が個人用と異なる |
/etc/cron.d/ | パッケージなどが追加するジョブ定義を置くディレクトリ |
/etc/cron.daily/, cron.hourly/, cron.weekly/, cron.monthly/ | 決まった周期で実行したいスクリプトを置くだけでよいディレクトリ |
常に電源が入っているとは限らないPC・ノートPC向けには、電源が入っていなかった間のジョブを起動時にまとめて実行するanacronという仕組みもあります。
新規ユーザーの初期設定と/etc/skel
useradd -mでホームディレクトリを作成すると、/etc/skelディレクトリの中身がそのまま新しいホームディレクトリにコピーされます。.bashrcなどの既定の設定ファイルをあらかじめ/etc/skelに用意しておくことで、新規ユーザー全員に同じ初期設定を配布できます。
$ ls -a /etc/skel
. .. .bash_logout .bashrc .profile
$ sudo userdel -r alice # -r: ホームディレクトリとメールスプールも含めて削除
userdelを-rなしで実行すると、ユーザーアカウントは削除されてもホームディレクトリは残ります。データの取り扱いには注意して選択してください。
atジョブの管理
| コマンド | 役割 |
|---|---|
atq | 予約中のatジョブの一覧を表示(at -lと同じ) |
atrm ジョブ番号 | 予約したジョブを取り消す(at -dと同じ) |
/etc/cron.allow・/etc/cron.deny(atは/etc/at.allow・/etc/at.deny)で利用できるユーザーを制限できます。allowファイルが存在する場合は、そこに記載されたユーザーのみが利用可能です。
systemdタイマーユニットによるスケジューリング
systemdを採用する環境では、cronに相当する定期実行の仕組みとしてタイマーユニット(.timerファイル)が用意されています。タイマーユニットは、同じ名前の.serviceユニットとペアで使い、「いつ」「何を」実行するかを分離して管理します。
/etc/systemd/system/backup.timer
[Unit]
Description=毎日3時にバックアップを実行するタイマー
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
/etc/systemd/system/backup.service
[Unit]
Description=バックアップスクリプトの実行
[Service]
Type=oneshot
ExecStart=/home/user/backup.sh
OnCalendarは、cronのような数値5つの書式ではなく、日時をそのまま近い形で記述できます。
| OnCalendarの書式例 | 意味 |
|---|---|
*-*-* 03:00:00 | 毎日午前3時0分0秒 |
Mon *-*-* 09:00:00 | 毎週月曜の午前9時 |
*-*-01 00:00:00 | 毎月1日の午前0時 |
weekly | 週1回(既定は月曜0時)を表すエイリアス |
daily | 毎日0時を表すエイリアス |
時刻を基準にするOnCalendar以外にも、システムやユニットの状態を基準にしたタイマー指定があります。
| ディレクティブ | 意味 |
|---|---|
OnBootSec= | システム起動から指定時間後に実行(例:OnBootSec=15min) |
OnUnitActiveSec= | 対応するユニットが最後にアクティブになってから指定時間後に実行(繰り返し実行に使える) |
AccuracySec= | 実行タイミングの許容誤差。既定では1分程度のずれを許容し、システム全体の起動タイミングを分散させる効果がある |
RandomizedDelaySec= | 指定時刻からランダムに遅延させる幅。多数のサーバーが同時刻に一斉実行して負荷が集中するのを避けたい場合に使う |
Persistent=true | マシンがその時刻に起動していなかった場合、次回起動時に未実行分を実行する(anacron的な役割) |
設定後は、対応する.serviceではなく.timerのほうを有効化・起動します。
$ sudo systemctl enable --now backup.timer
$ systemctl list-timers # 登録済みタイマーの一覧と、次回・前回の実行時刻を確認
NEXT LEFT LAST PASSED UNIT ACTIVATES
Tue 2026-08-25 03:00:00 JST 14h left Mon 2026-08-24 03:00:00 JST 10h ago backup.timer backup.service
この行のこの値に注目: list-timersの出力にあるNEXT/LAST列は、それぞれ次回の実行予定時刻と前回実際に実行された時刻を表し、ACTIVATES列でどの.serviceユニットが起動されるかが分かります。この一覧に自分が登録したタイマーが出てこない場合、.timerファイル自体を有効化し忘れている(.serviceだけをenableしてしまった)ことが多い間違いです。
一度きりの一時的なジョブをその場で仕込みたい場合は、ユニットファイルを作らずにsystemd-runで直接スケジューリングすることもできます。
$ systemd-run --on-calendar="2026-08-22 22:00:00" /home/user/shutdown-check.sh
Running timer as unit: run-xxxx.timer
Will run service as unit: run-xxxx.service
グループ管理コマンドの補足
| コマンド | 役割 |
|---|---|
groupmod -n 新名 旧名 | グループ名を変更 |
groupdel グループ名 | グループを削除(そのグループを主グループとするユーザーが残っていると削除できない) |
gpasswd -a ユーザー名 グループ名 | ユーザーをグループに追加(usermod -aGと同様の効果) |
newgrp グループ名 | 現在のシェルで有効な主グループを一時的に切り替える |
1人のユーザーには「主グループ(プライマリグループ)」が1つと、「副グループ(セカンダリグループ)」が複数存在できます。新規ファイル作成時に自動的に割り当てられる所有グループは主グループのほうです。idコマンドの出力で最初に表示されるgidが主グループ、groupsの並びで2番目以降に出てくるものが副グループに該当します。
よくある間違い
15 * * * *と書くと、これは「毎時15分ちょうどに1回だけ」実行する設定になります。「15分間隔で」実行したい場合は*/15 * * * *のようにスラッシュを使う必要があります。似たような書式ですが意味がまったく異なるため注意しましょう。
登録したはずのcronが動かないときの確認ポイント
「crontabに書いたのに実行された形跡がない」というトラブルは非常によくあります。原因の多くは次のいずれかに当てはまります。
- PATHが対話シェルと異なる: cronはログインシェルとは別の、非常に限られたPATHでコマンドを実行します。スクリプト内でコマンドをフルパス(
/usr/bin/python3など)で書くか、スクリプトの先頭でPATHを明示的に設定しておくと安全です。 - カレントディレクトリが想定と違う: cronの実行時、カレントディレクトリは実行ユーザーのホームディレクトリになるのが一般的です。相対パスでファイルを指定していると、意図した場所とは違う場所を参照してしまいます。
- そもそもcron自体が実行されていない:
systemctl status cron(またはcrond)でサービス自体が動作しているかを確認しましょう。
実行結果を確認したいときは、まずログ(journalctl -u cronや/var/log/cronなど、ディストリビューションにより異なる)を見て、そもそもジョブが起動したかどうかを確認するのが最初の一歩です。この種のトラブルシューティングの詳しい流れは、トラブルシューティングの記事でも扱っています。
パスワードポリシーの強制
組織で複数のユーザーアカウントを管理する場合、個々のユーザー任せにせず、パスワードの有効期限や複雑さの要件をシステム側で強制することが望まれます。有効期限はchageコマンドで確認・設定でき、chage -M 90 aliceのように指定すると、そのユーザーのパスワードを90日ごとに変更させることができます。パスワードの複雑さ(最低文字数や記号の必須化など)についてはpam_pwqualityのようなPAMモジュール(上級編で扱います)で制御するのが一般的です。個人の学習環境では意識する機会が少ないかもしれませんが、複数人でサーバーを運用する現場では欠かせない管理項目です。