test-your-sysadmin-skillsを翻訳してみて答えられなかった質問８選

https://github.com/trimstray/test-your-sysadmin-skills

というリポジトリがあります。

システム管理者としてどれくらいの実力があるかの質問と答えを集めたものです。
これで自分の実力を知ることができます。

このリポジトリをほぼChatGPTに投げて日本語にしてみました。

https://github.com/misogihagi/test-your-sysadmin-skills/blob/master/README.md



[ジュニア](https://github.com/misogihagi/test-your-sysadmin-skills/blob/master/README.md#junior-sysadmin)

[一般](https://github.com/misogihagi/test-your-sysadmin-skills/blob/master/README.md#regular-sysadmin)

[シニア](https://github.com/misogihagi/test-your-sysadmin-skills/blob/master/README.md#senior-sysadmin)

とレベルが別れているのですが、一般レベルはなんとかなりつつもシニアレベルが大変でした。

ここでは筆者が答えられなかった質問とその答えを載せておきます。
もっと挑戦したい方はぜひ以下へ↓

https://github.com/misogihagi/test-your-sysadmin-skills/tree/master

## サーバーをデバッグしようとしている他の管理者が誤って入力してしまった：chmod -x /bin/chmod。パーミッションをデフォルトに戻すには？

<details>
<summary>答え</summary><br>

```bash
# 1:
cp /bin/ls chmod.01
cp /bin/chmod chmod.01
./chmod.01 700 file

# 2:
/bin/busybox chmod 0700 /bin/chmod

# 3:
setfacl --set u::rwx,g::---,o::--- /bin/chmod

# 4:
/usr/lib/ld*.so /bin/chmod 0700 /bin/chmod
```

</details>


## useradd または adduser コマンドを使わずに新しいユーザーを追加する方法は？

useraddやadduserコマンドが何をしているかというのを答える質問
手動でやると面倒

<details>
<summary>答え</summary><br>

1. `vipw` コマンドを使って、<code>/etc/passwd</code> にユーザーの詳細を追加します：

```bash
# username:password:UID:GID:Comments:Home_Directory:Login Shell
user:x:501:501:test user:/home/user:/bin/bash
```

   > 構文には注意してください。直接エディタで編集しないでください。`vipw` はファイルをロックするため、他のコマンドが同時にファイルを更新しようとすることはありません。

2. 同じ名前のグループを <code>/etc/group</code> に `vigr` で作成する必要があります（`vipw` と似たツールです）。

```bash
user:x:501:
```

3. ユーザーにパスワードを与えます:

```bash
passwd user
```

4. `mkdir` コマンドを使ってユーザーのホームディレクトリを作成します：

```bash
mkdir -m 0700 /home/user
```

5. `/etc/skel` から新しいホームディレクトリにファイルをコピーします：

```bash
rsync -av --delete /etc/skel/ /home/user
```

6. `chown` と `chmod` を使って所有権と権限を修正します：

```bash
chown -R user:user /home/user
chmod -R go-rwx /home/user
```

</details>


## アプリケーションにパフォーマンスの問題が発生しています。最適化すべきコードを見つける必要があります。Linux環境でアプリをプロファイルする方法は？

あまりシステム管理っぽくない質問
ツールにお任せしているところをコマンドでできるかな？

<details>
<summary>答え</summary>

> 理想的には、プロセスにアタッチして、メモリ使用量、スレッド数、CPU使用率の定期的なスナップショットを記録するアプリが必要です。

1. `top`をバッチモードで使用できます。バッチモードでは、終了するまで、または指定した回数の反復が完了するまで実行されます。

```bash
top -b -p `pidof a.out`
```

または

```bash
top -b -p `pidof a.out` -n 100
```

2. psも使用できます (例えばシェルスクリプトで):

```bash
ps --format pid,pcpu,cputime,etime,size,vsz,cmd -p `pidof a.out`
```

> Linuxマシンでアプリケーションのパフォーマンスを記録する手段が必要です。

1. パフォーマンスデータを記録する:
 
```bash
perf record -p `pidof a.out`
```

または10秒間記録するには:

```bash
perf record -p `pidof a.out` sleep 10
```

または、コールグラフを記録するには:

```bash
perf record -g -p `pidof a.out`
```

2) 記録されたデータを解析する

```bash
perf report --stdio
perf report --stdio --sort=dso -g none
perf report --stdio -g none
perf report --stdio -g
```

**これはテストプログラムのプロファイリングの例です**

1. テストプログラム（C++）を実行します:

```bash
./my_test 100000000
```

2. 実行中のプロセスのパフォーマンスデータを記録します:

```bash
perf record -g  -p `pidof my_test` -o ./my_test.perf.data sleep 30
```

3. 次に、モジュールごとの負荷を分析します:

```bash
perf report --stdio -g none --sort comm,dso -i ./my_test.perf.data

# Overhead  Command                 Shared Object
# ........  .......  ............................
#
    70.06%  my_test  my_test
    28.33%  my_test  libtcmalloc_minimal.so.0.1.0
     1.61%  my_test  [kernel.kallsyms]
```

4. 次に、機能ごとの負荷を分析します:

```bash
perf report --stdio -g none -i ./my_test.perf.data | c++filt

# Overhead  Command                 Shared Object                       Symbol
# ........  .......  ............................  ...........................
#
    29.30%  my_test  my_test                       [.] f2(long)
    29.14%  my_test  my_test                       [.] f1(long)
    15.17%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator new(unsigned long)
    13.16%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator delete(void*)
     9.44%  my_test  my_test                       [.] process_request(long)
     1.01%  my_test  my_test                       [.] operator delete(void*)@plt
     0.97%  my_test  my_test                       [.] operator new(unsigned long)@plt
     0.20%  my_test  my_test                       [.] main
     0.19%  my_test  [kernel.kallsyms]             [k] apic_timer_interrupt
     0.16%  my_test  [kernel.kallsyms]             [k] _spin_lock
     0.13%  my_test  [kernel.kallsyms]             [k] native_write_msr_safe

  ...
```

5. 次に、コールチェインを分析します:

```bash
perf report --stdio -g graph -i ./my_test.perf.data | c++filt

# Overhead  Command                 Shared Object                       Symbol
# ........  .......  ............................  ...........................
#
    29.30%  my_test  my_test                       [.] f2(long)
            |
            --- f2(long)
               |
                --29.01%-- process_request(long)
                          main
                          __libc_start_main

    29.14%  my_test  my_test                       [.] f1(long)
            |
            --- f1(long)
               |
               |--15.05%-- process_request(long)
               |          main
               |          __libc_start_main
               |
                --13.79%-- f2(long)
                          process_request(long)
                          main
                          __libc_start_main

  ...
```

この時点で、プログラムがどこに時間を費やしているかがわかります。

また、アプリケーションのプロファイルを作成する簡単な方法は、`pstack`ユーティリティまたは`lsstack`を使用することです。

もう一つのツールはValgrindです。これをお勧めします。まずプログラムを実行します:

```bash
valgrind --tool=callgrind --dump-instr=yes -v --instr-atstart=no ./binary > tmp
```

プログラムが動作しているときに、プロファイリングを開始するには別のウィンドウで以下を実行します:

```bash
callgrind_control -i on
```

これでプロファイリングがオンになります。オフにして全タスクを停止するには次のコマンドを使用します:

```bash
callgrind_control -k
```

これで、現在のディレクトリに`callgrind.out.*`という名前のファイルが生成されます。プロファイリングの結果を確認するには次のコマンドを使用します:

```bash
kcachegrind callgrind.out.*
```

次のウィンドウで**Self**列のヘッダーをクリックすることをお勧めします。そうしないと、`main()`が最も時間を消費しているタスクとして表示されてしまいます。

</details>


## プロダクションサーバーでルートによって実行されたすべてのコマンドをログに記録するには？

auditdを知っているか使えるかの質問
筆者は使ったことないです

<details>
<summary>答え</summary><br>

`auditd`がこの作業には適切なツールです：

1. `/etc/audit/audit.rules` に以下の2行を追加します：

```bash
-a exit,always -F arch=b64 -F euid=0 -S execve
-a exit,always -F arch=b32 -F euid=0 -S execve
```

これにより、ルート（euid=0）によって実行されたすべてのコマンドが追跡されます。なぜ2つのルールが必要なのか？`execve` システムコールは、32ビットおよび64ビットの両方のコードで追跡する必要があります。

2. ログに `auid=4294967295` メッセージを表示させないようにするには、カーネルのコマンドラインに `audit=1` を追加します（`/etc/default/grub` を編集）。

3. 以下の

```bash
session  required                pam_loginuid.so
```

を、ログインに関連するすべてのPAM設定ファイル（`/etc/pam.d/{login,kdm,sshd}`）に追加しますが、`su` または `sudo` に関連するファイルには追加しません。これにより、`sudo` または `su` を呼び出すときに、`auditd` が呼び出し元ユーザーのUIDを正しく取得できるようになります。

システムを再起動してください。

ログインしてコマンドを実行してみましょう：

```bash
$ id -u
1000
$ sudo ls /
bin  boot  data  dev  etc  home  initrd.img  initrd.img.old  lib  lib32  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  scratch  seLinux  srv  sys  tmp  usr  var  vmlinuz  vmlinuz.old
$ sudo su -
# ls /etc
[...]
```

`/var/log/audit/auditd.log` を読み取って、どのコマンドがログに記録されたかを確認してください。

</details>


## 2>&-、2>/dev/null、|&、&>/dev/null、および >/dev/null 2>&1 の違いを説明してください。

エラー出力やファイルディスクリプタについて
とっさに聞かれてもわからないかも

<details>
<summary>答え</summary><br>

- **番号 1** = 標準出力（`STDOUT`）
- **番号 2** = 標準エラー（`STDERR`）
- 明示的に番号が指定されていない場合、シェル（bash）はデフォルトで**番号 1**を使用します。

これらの機能について説明します。

`2>&-`

一般的な形式は `M>&-` で、ここで **"M"** はファイルディスクリプタ番号です。これは、指定されたファイルディスクリプタ **"M"** の出力を閉じます。

`2>/dev/null`

一般的な形式は `M>/dev/null` で、ここで **"M"** はファイルディスクリプタ番号です。これは、ファイルディスクリプタ **"M"** の出力を `/dev/null` にリダイレクトします。

`2>&1`

一般的な形式は `M>&N` で、ここで **"M"** と **"N"** はファイルディスクリプタ番号です。これは、ファイルディスクリプタ **"M"** と **"N"** の出力を単一のストリームに結合します。

`|&`

これは `2>&1 |` の省略形です。Bash 4 で追加されました。

`&>/dev/null`

これは `>/dev/null 2>&1` の省略形です。ファイルディスクリプタ 2（`STDERR`）とファイルディスクリプタ 1（`STDOUT`）の出力を `/dev/null` にリダイレクトします。

`>/dev/null`

これは `1>/dev/null` の省略形です。ファイルディスクリプタ 1（`STDOUT`）の出力を `/dev/null` にリダイレクトします。

有用なリソース：

- [2>&-、2>/dev/null、|&、&>/dev/null、および >/dev/null 2>&1 の違い](https://unix.stackexchange.com/questions/70963/difference-between-2-2-dev-null-dev-null-and-dev-null-21)
- [第20章 I/O リダイレクション](http://www.tldp.org/LDP/abs/html/io-redirection.html)

</details>

## nohup、disown、& の違い。すべてを一緒に使用した場合にどうなりますか？

似たようなものの細かい違いについて
nohup &はよく使われますがどのような違いがあるのでしょう

<details>
<summary>答え</summary><br>

- `&` はジョブをバックグラウンドで実行し、入力の読み込みをブロックし、シェルがジョブの完了を待たないようにします
- `disown` はプロセスをシェルのジョブ制御から削除しますが、ターミナルへの接続は維持されます。これにより、シェルはプロセスに**SIGHUP**を送信しなくなります。明らかに、これはバックグラウンドジョブにのみ適用されるため、フォアグラウンドジョブが実行中にこの操作を行うことはできません
- `nohup` はプロセスをターミナルから切り離し、その出力を `nohup.out` にリダイレクトし、**SIGHUP** から保護します。効果の1つ（名前に関連するもの）は、プロセスが送信された**SIGHUP**を受け取らなくなることです。ジョブ制御とは完全に独立しており、原理的にはフォアグラウンドジョブにも使用できます（ただし、あまり便利ではありません）

これらをすべて一緒に使用すると、プロセスはバックグラウンドで実行され、シェルのジョブ制御から削除され、ターミナルから効果的に切り離されます。

</details>


## inodeに格納されているフィールドはどれですか？
inodeの話
どのような情報が入っているかはよく知らない人も多いハズ

<details>
<summary>答え</summary><br>

POSIXシステム内では、ファイルには次の属性があり、`stat` システムコールによって取得できます：

- **デバイスID**（これはファイルを含むデバイスを識別します。つまり、シリアル番号の一意性の範囲です。）

- **ファイルモード**（ファイルの種類と、ファイルの所有者、そのグループ、および他のユーザーがファイルにどのようにアクセスできるかを決定します）
- **リンクカウント**（inodeを指すハードリンクの数を示します）
- ファイルの**ユーザーID**
- ファイルの**グループID**
- ファイルがデバイスファイルの場合、その**デバイスID**
- ファイルの**サイズ**（バイト単位）
- **タイムスタンプ**（inode自体が最後に変更された時刻（ctime、inode変更時間）、ファイル内容が最後に変更された時刻（mtime、修正時間）、最後にアクセスされた時刻（atime、アクセス時間））
- 推奨される**I/Oブロックサイズ**
- このファイルに割り当てられた**ブロックの数**

</details>


## カーネルの種類とその違いを説明してください。

カーネルに種類あったんだ…

<details>
<summary>答え</summary><br>

**モノリシックカーネル**

従来のこのタイプのカーネルアーキテクチャでは、プロセス管理やメモリ管理、割り込み処理などの基本的なシステムサービスがカーネル空間内の単一モジュールにまとめられていました。このアーキテクチャには、以下のような深刻な欠点がありました：

- カーネルのサイズが非常に大きい
- メンテナンス性が低く、新しい機能を追加したりバグ修正を行うたびに、カーネル全体を再コンパイルする必要があり、数時間かかることもある

現代のモノリシックアーキテクチャでは、カーネルは動的にロードおよびアンロードできる複数のモジュールで構成されています。このモジュラーアプローチにより、OSの機能を簡単に拡張できるようになり、特定のモジュールに変更やバグ修正があった場合、関連するモジュールだけをロードおよびアンロードするだけで済むため、カーネルのメンテナンスが非常に簡単になりました。

Linuxはモノリシックモジュラーアプローチを採用しています。

**マイクロカーネル**

このアーキテクチャは、モノリシックアプローチで制御できなかったカーネルコードの増大に対応するために開発されました。このアーキテクチャでは、デバイスドライバの管理、プロトコルスタック、ファイルシステムなどの基本的なサービスがユーザー空間で実行されます。

このアーキテクチャでは、OSの基本サービスがユーザー空間の一部となり、システム内の他のプログラムがこれらのサービスを利用する際に、プロセス間通信（IPC）を介してサーバーとして実行されます。

例: デバイスドライバ、ネットワークプロトコルスタック、ファイルシステム、グラフィックスなどにサーバーがあります。マイクロカーネルのサーバーは、他のプログラムと同様にデーモンプログラムですが、一部のサーバーには物理メモリの一部にアクセスできる特権が与えられています。

**ハイブリッドカーネル（モジュラーカーネル）**

これは上記の2つの組み合わせであり、OSサービスがカーネル空間に存在し、メッセージパッシングやパフォーマンスオーバーヘッドがなく、ユーザー空間でサービスを実行することによる信頼性の向上もありません。

これは、MicrosoftのNTカーネル（最新のWindowsバージョンまで）で使用されています。


</details>