ssh-keygen -N '' -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
- -N ''でパスフレーズをなしに設定
- -t ed25519でED25519の鍵を作成。他にもRSAやECDSAのホスト鍵を作ることが一般的だが、私の環境では、すべてのSSHクライアントがED25519に対応しているのでこれだけ作成
- -fは、作成した鍵を保存するパスを指定するオプション
ssh-keygen -N '' -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
-netdev user,id=NETDEV_ID \ -device virtio-net-pci,netdev=NETDEV_IDあるいは単純に以下のようにしてもよい。
-nic user,model=virtio-net-pci
-netdev user,id=NETDEV_ID,hostfwd=tcp::5522-:22 \
-device virtio-net-pci,netdev=NETDEV_ID
-nicを用いる記述でもポート転送を指定できます。以下の例ではさらに、複数のポートを転送する例を記載します。
-nic user,model=virtio-net-pci,hostfwd=tcp::5522-:22,hostfwd=tcp::5580-:80
-netdev tap,id=NETDEV_ID \
-device virtio-net-pci,mac=02:12:34:56:78:9a,netdev=NETDEV_ID
ブリッジに関しても-nicオプションでより簡潔に記載することが可能。
-nic tap,model=virtio-net-pci,mac=02:12:34:56:78:9a
-nic none
$ qemu-img create -f qcow2 drive.img 10G Formatting 'drive.img', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=10737418240 lazy_refcounts=off refcount_bits=16lsに-sオプションを指定してファイルサイズを見てみる。一番左端の196KiBは、そのファイルのストレージ上に占めるサイズ。 所有者foo fooの右側の193KiBは、そのファイルのサイズ。 両者は、ほぼ同じ(これが一般的)。上記コマンドで10GiBのドライブイメージファイルを作成したが、実際のファイルサイズは初期状態では非常に小さい。
$ ls -lhs drive.img 196K -rw-r--r-- 1 foo foor 193K Mar 23 20:30 drive.img
$ qemu-img create -f raw drive.img 10G Formatting 'drive.img', fmt=raw size=10737418240QCOW2の場合と同様にlsでファイルサイズを調べると、上記コマンドで指定したとおり10GiBである。しかし、一番左端の実サイズは非常に小さい。実はRAW形式も、Linuxの多くのファイルシステム(例えばext4)では、スパースファイルと呼ばれる状態のファイルとして作成される。利用に応じて実サイズが増加する。
$ ls -lhs drive.img 4.0K -rw-r--r-- 1 foo foo 10G Mar 23 20:31 drive.img
-drive id=DRIVE_ID,format=qcow2,file=FILE_NAME.qcow2,if=virtio
-drive id=DRIVE_ID,format=raw,file=FILE_NAME.img,if=virtio
-device virtio-scsi-pci次いでドライブを作成
-drive id=DRIVE_ID,format=qcow2,file=FILE_NAME.qcow2,if=none \ -device scsi-hd,drive=DRIVE_ID
-device nec-usb-xhci,id=xhci次いでドライブを作成。
-drive id=DRIVE_ID,format=raw,file=FILE_NAME.raw,if=none \ -device usb-storage,bus=xhci.0,drive=DRIVE_ID
$ tar tf archive.tar.gz dir1/ dir1/b.dat dir1/a.txt
mkdir -p flower/sun tar xf archive.tar.gz -C flower/sun
$ find flower -type f flower/sun/dir1/b.dat flower/sun/dir1/a.txt
Linuxにはmakeというコマンドがあります。もともとはC言語などで作られたプログラムをコンパイルやリンクするために開発されました。そして、今もその用途が中心です。 大規模なプログラムでは、ソースコードファイルが数千や数万以上になります。いくつかのソースコードファイルを変更するたびに、全てをコンパイルしなおすと膨大な時間がかかります。そのため、makeは、変更があったソースコードのみを抽出してコンパイルする手段を提供します。
では、どうやって変更があったソースコードを検出しているのでしょうか?実は、その仕組みはとても単純です。ソースコードのタイムスタンプ(変更日時)とそれをコンパイルして生成されるバイナリファイルのタイムスタンプを比較するだけです。このため、何かのファイルから別のファイルを生成するような用途には、プログラムに限らずに利用できます。例えば、数値データのCSVファイルからグラフファイルを作成するような場合です。
出力ファイル: 入力ファイル
[TAB]処理方法
また、出力ファイルと入力ファイルは、より抽象的に、それぞれ、ターゲットと依存ファイルと呼ばれることもあります。
#include <stdio.h>
int main() {
printf("Happiness depends upon ourselves.\n");
return 0;
}
コマンドラインからビルドするには以下のように入力します。
gcc -o prog prog.cつまり、先に述べた3つの情報は次のようになります。
prog: prog.c
gcc -o prog prog.c
Makefileがあるディレクトリでmakeと入力すると以下のようにコンパイルが実行され、progが作成されていることが分かります。
また、makeの副次的な利点として、gccのコマンドラインオプションすべてを入力しなくても良い点があります。
$ make gcc -o prog prog.c
$ ls -l total 28 -rw-r--r-- 1 foo foo 33 Mar 21 09:01 Makefile -rwxr-xr-x 1 foo foo 16608 Mar 21 10:44 prog -rw-r--r-- 1 foo foo 100 Mar 21 09:01 prog.c
$ make make: 'prog' is up to date.冒頭で説明したように、出力ファイルのタイムスタンプが、入力ファイルのタイムスタンプより新しいため、makeは何も処理を実行しなかったのです。ここで、以下のようにtouchコマンドを実行して、入力ファイルのタイムスタンプを更新します。
$ touch prog.c $ ls -l total 28 -rw-r--r-- 1 kyamato kyamato 33 Mar 21 09:01 Makefile -rwxr-xr-x 1 kyamato kyamato 16608 Mar 21 10:44 prog -rw-r--r-- 1 kyamato kyamato 100 Mar 21 11:01 prog.cこの状態でmakeを実行すると、コンパイルが行われます。
$ make gcc -o prog prog.c
本記事では、make概要とMakefileの基本的な記述方法について説明しました。次回は、Makefileに複数のルールを記載する方法を説明します。
以下には、make入門の全記事がリストアップされています。
Linuxでは、すべてのものはファイルとして扱われます。例えば、キーボード入力や画面出力もファイルとして扱われます。 具体的に見ていきましょう。まず以下のように入力してみます。この出力にはいろいろな知見が含まれます。順に説明します。
# ls -l /proc/self/fd total 0 lrwx------ 1 root root 64 Mar 19 19:26 0 -> /dev/pts/1 lrwx------ 1 root root 64 Mar 19 19:26 1 -> /dev/pts/1 lrwx------ 1 root root 64 Mar 19 19:26 2 -> /dev/pts/1 lr-x------ 1 root root 64 Mar 19 19:26 3 -> /proc/147982/fd
ls -l /proc/self/fd > output.txt
作成されたファイルoutput.txtの内容(すなわち、lsがオープンしているファイル)は次のとおりです。
total 0 lrwx------ 1 root root 64 Mar 21 08:20 0 -> /dev/pts/1 l-wx------ 1 root root 64 Mar 21 08:20 1 -> /root/output.txt lrwx------ 1 root root 64 Mar 21 08:20 2 -> /dev/pts/1 lr-x------ 1 root root 64 Mar 21 08:20 3 -> /proc/160788/fdつまり、コマンドライン上で>を使ってファイルへ保存するとき、lsコマンドの標準出力はリダイレクトされたファイルに なっていることが分かります。以下のその様子を図示します。
ls -l /proc/self/fd > output.txt 2> error.txt
output.txtの内容を確認すると以下のようになっています。
total 0 lrwx------ 1 root root 64 Mar 21 01:00 0 -> /dev/pts/5 l-wx------ 1 root root 64 Mar 21 01:00 1 -> /root/output.txt l-wx------ 1 root root 64 Mar 21 01:00 2 -> /root/error.txt lr-x------ 1 root root 64 Mar 21 01:00 3 -> /proc/75664/fd以下にこの状態を図示します。
ls -l /proc/self/fd > output.txt 2&>1
output.txtの内容は次のとおりです。
total 0 lrwx------ 1 root root 64 Mar 21 02:33 0 -> /dev/pts/1 l-wx------ 1 root root 64 Mar 21 02:33 1 -> /root/output.txt l-wx------ 1 root root 64 Mar 21 02:33 2 -> /root/output.txt lr-x------ 1 root root 64 Mar 21 02:33 3 -> /proc/75694/fdこの状態を図示すると以下のようになります。
less a.txtこの場合、4番に引数で指定したa.txtが割り当てられています。標準入力は端末のままです。 lessは、標準入出力とは別に引数で与えられたファイルをオープンしたということになります。 なお、このlessのPIDの調べ方は、次節の「パイプでプロセス間の入出力を連結する場合」で説明します。
total 0 lrwx------ 1 root root 64 Mar 21 03:11 0 -> /dev/pts/1 lrwx------ 1 root root 64 Mar 21 03:11 1 -> /dev/pts/1 lrwx------ 1 root root 64 Mar 21 03:11 2 -> /dev/pts/1 lr-x------ 1 root root 64 Mar 21 03:11 3 -> /dev/tty lr-x------ 1 root root 64 Mar 21 03:11 4 -> /root/a.txtこの状態を図示すると以下のようになります。
less < a.txt
答えは次のとおり、標準入力は<の右側に指定したファイルになっています。
この違いについては、この記事の最後の「標準入出力は誰が設定するのか?」で詳しく説明します。
total 0 lr-x------ 1 root root 64 Mar 21 04:29 0 -> /root/a.txt lrwx------ 1 root root 64 Mar 21 04:29 1 -> /dev/pts/6 lrwx------ 1 root root 64 Mar 21 04:29 2 -> /dev/pts/6 lr-x------ 1 root root 64 Mar 21 04:29 3 -> /dev/ttyまた、これまで同じく図も示します。
cat a.txt | grep abc
この場合の標準入出力を見てみます。 ただし、上記のコマンドは一瞬で終了するため、実行中の/proc/[PID]/fdを調べることができません。 そのため、少しコマンドを工夫しますが、その前にcatやgrepを実行するbashのPID(プロセスID)を調べておきます。
変数$$には、実行中のbashのPIDが格納されています。以下のとおり、操作しているbashの74570であり、そのbashから実行されたコマンドの親PIDは、74570になります。
$ echo $$ 74570次いで以下のコマンドを実行します。catに引数がありません。 この場合、catは標準入力すなわちキーボードから入力を待っている状態になり、ファイルを読み込んだ時のように瞬時には終了しなくなります。
cat | grep abcここでcatとgrepのPID(プロセスID)を調べます。同じPCの別の端末で、先ほど調べたbashのPIDを親にもつプロセスを探します。
$ ps --ppid 74570 TIME CMD 75104 pts/6 00:00:00 cat 75110 pts/6 00:00:00 grepcatとgrepのPIDはそれぞれ75104と75110であることが分かりました。 それぞれについて、/proc/[PID]/fd以下のファイルを見ます。
$ ls -l /proc/75104/fd total 0 lrwx------ 1 root root 64 Mar 20 09:01 0 -> /dev/pts/1 l-wx------ 1 root root 64 Mar 20 09:01 1 -> 'pipe:[936222]' lrwx------ 1 root root 64 Mar 20 09:01 2 -> /dev/pts/1 $ ls -l /proc/75110/fd total 0 lr-x------ 1 root root 64 Mar 20 09:01 0 -> 'pipe:[936222]' lrwx------ 1 root root 64 Mar 20 09:01 1 -> /dev/pts/1 lrwx------ 1 root root 64 Mar 20 09:01 2 -> /dev/pts/1上記の結果から、catの標準出力がpipe:[936222]というのになっており、grepの標準入力も同じくpipe:[936222]になっています。 これは、下図のようにcatがパイプというファイルに出力を書き込み、grepは同じパイプというファイルからデータを読み出していることを意味します。 また、catの標準入力や標準エラー出力、grepの標準出力と標準エラー出力は、端末である/dev/pts/1となっています。つまり、catは端末を通じてキーボードからデータを入力し、grepが標準出力に書き込んだデータは、端末に表示されることが分かります。