/ dev/sda2の最後の1024バイトだけを取得しようとしています。私がする時 Sudo tail -c 1024 /dev/sda2 | hd
、Ctrl-Cを押すまでプロンプトがハングします。しかし、私がtail -c 1024 ddfilecopyofsda2 | hd
、ファイルの最後の1024バイトのNice出力をすぐに取得します。私はここを読んだ( https://unix.stackexchange.com/questions/60034/what-are-character-special-and-block-special-files-in-a-unix-system ) 「ブロックデバイスは通常シーク可能です」ので、何が欠けていますか?
ブロックデバイスの最後の1024バイトを取得する1つの方法は次のとおりです。
_last_bytes() { Sudo dd if=$2 iflag=skip_bytes skip=$(($(Sudo blockdev --getsize64 $2) - $1)) bs=1M ; } ; last_bytes 1024 DEVICE
_
DEVICE
をデバイスパスに置き換えます。あなたの場合、あなたは_/dev/sda2
_を使うでしょう。
答えるもっと興味深い質問のために…
tail -c 1024 /dev/sda2
_がディスク全体を検索するのはなぜですか?その理由は、tail
がどのように実装されているかです。 tail
が読み取っているファイルのサイズを知っているとき、それはシークする量を正確に知っています。それ以外の場合は、ファイルを読み取るか、ストリーミングして、カウントバックする距離を確認する必要があります。
パイプの場合、_cat /dev/sda2 | tail -c 1024
_のように意味があります。 tail
はコンテンツをストリームとして受信しており、データがいつ終了するかを知る方法がありません。
_tail -c 1024 /dev/sda2
_が_/dev/sda2
_のサイズを把握できると期待するかもしれませんが、実際には、tail
が_/dev/sda2
_を検索すると、ではなくブロックデバイスとして開かれます。通常のファイル。
実装の詳細は、tail
が fstat()
を呼び出してファイルに関する情報を取得することです。
tail
ファイルを開くstrace
の例のtail
の関連部分は次のとおりです。
_21:30:27 open("/var/log/syslog", O_RDONLY) = 3
21:30:27 fstat(3, {st_dev=makedev(0, 22), st_ino=4715, st_mode=S_IFREG|0640, st_nlink=1, st_uid=104, st_gid=4, st_blksize=131072, st_blocks=54, st_size=175500, st_atime=2017/11/10-21:28:39.243133398, st_mtime=2017/11/10-21:30:20.438031639, st_ctime=2017/11/10-21:30:20.438031639}) = 0
21:30:27 lseek(3, 0, SEEK_CUR) = 0
21:30:27 lseek(3, 174476, SEEK_SET) = 174476
_
fstat()
は_st_size=175500
_を提供します。ここで、tail
は1024バイトをカウントバックする必要があります。
175500-1024 = 174476
…そしてこれはまさに
tail
が行うことです:_lseek(3, 174476, SEEK_SET) = 174476
_
tail
fstat()
は今回はサイズを返しません!:
_21:29:43 open("/dev/sda", O_RDONLY) = 3
21:29:43 fstat(3, {st_dev=makedev(0, 6), st_ino=17488, st_mode=S_IFBLK|0660, st_nlink=1, st_uid=0, st_gid=6, st_blksize=4096, st_blocks=0, st_rdev=makedev(8, 0), st_atime=2017/11/10-09:21:15.643998960, st_mtime=2017/11/10-09:21:15.555998962, st_ctime=2017/11/10-09:21:15.555998962}) = 0
_
_st_size
_がないと、tail
はどこまでシークするかを知ることができないため、デフォルトでブロックデバイス全体を最後まで読み取ります。
これが、通常、dd
のような通常のファイル用のツールではなく、tail
のようなブロックデバイスツールを使用してブロックデバイスを操作する必要がある理由です。
「_blockdev --getsize64
_はどのようにしてブロックデバイスのサイズをすばやく取得するのですか?」と質問するかもしれません。
これが_Sudo strace -vvvfts1000 blockdev --getsize64 /dev/sda
_です:
_21:53:15 open("/dev/sda", O_RDONLY) = 3
21:53:15 ioctl(3, BLKGETSIZE64, [512110190592]) = 0
_
blockdev
はブロックデバイスのioctlを取得するためのものであり、_BLKGETSIZE64
_はブロックデバイスのサイズを取得するためのものです。
whytail
が_BLKGETSIZE64
_を実行しない理由については、わかりません。 ソースコード は次のことを示しています。
_#define IS_TAILABLE_FILE_TYPE(Mode) \
(S_ISREG (Mode) || S_ISFIFO (Mode) || S_ISSOCK (Mode) || S_ISCHR (Mode))
_
その行から、 S_ISBLK()
がなければ、作者はtail
がブロックデバイスをサポートすることを意味していなかったことがわかります。