ファイルaが存在するときの「cp /dev/zero a」の効果

ファイルaが存在するときの「cp /dev/zero a」の効果

それがa存在し、私が入ると

cp /dev/zero a

古いコンテンツを上書きできますかa?それとも単に次のようなものを得ることができますか?

rm a
cp /dev/zero a

PS。これがファイルを安全に削除する正しい方法であるとは言いません。ただ特定のコマンドの効果が気になるだけです。

答え1

/dev/zeroファイルにコピーするのはなぜですか?

  • 安全に削除しますかa?もしそうなら、cp間違ったツールがあります。shredハードドライブを使用していること、fstrimSSDを使用していることを確認してください。 (わからない他のツールがある可能性があるため、Googleで「安全な削除」を検索することをお勧めします。)

  • 無限を理解していますか/dev/zero? 0を無限に返すので、cp含まれるファイルシステムがいっぱいになるaまで完了しません。

  • ただし、cpスパースファイル検出の一部としてすべてゼロのページ書き込みが抑制されるため、これは決して発生しない可能性があります。

  • すべてゼロで指定されたサイズのファイルを生成しますか?cpそれでも間違ったツールです。ddからコピーするバイト数を指定するには、を使用する必要があります/dev/zero

一般に、cp一般ファイルを別の一般ファイルにコピーするときに興味があるのは、コピーが論理的に同じであることだけです。

デバイスファイルを使用している場合、またはネイティブファイルブロックの処理方法を制御する場合は、別のプログラムを使用する必要があります。

答え2

私はファイルを開いて最初から書き込むと、既存のすべてのブロックがすぐに解放され(まだ既存の内容を含む)、cpがゼロパディングのための新しいブロックを取得することになると思います。

さらに、ファイルはパーティション全体を埋めるまで拡張されます。つまり、元のサイズは維持されません。

このコマンドには、statを使用して元のサイズを検索し、それをブロック全体に丸め、オプションを使用してゼロのサイズを元のブロックと同じサイズに調整するddオプションがあります。conv=notrunccountbs

編集:シェル>リダイレクトは同じinode番号を保持しますが、すぐにファイルサイズを0ブロックに減らし、空き容量を確保するというテストで確認されました。

cpのstraceは、mmap領域を介したファイルの一般的な上書きを示しています。

open("foo.tiny", O_RDONLY)              = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=8192, ...}) = 0
open("foo.copy", O_WRONLY|O_CREAT|O_EXCL, 0644) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
mmap(NULL, 139264, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc295d30000
read(3, "\0\0\0\0"..., 131072) = 8192
write(4, "\0\0\0\0"..., 8192) = 8192
read(3, "", 131072)                     = 0
close(4)                                = 0
close(3)                                = 0
munmap(0x7fc295d30000, 139264)          = 0
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0

結論は、これがcpあなたの秘密データを空きリストに捨て、その後に割り当てられたブロックを上書きするということです。

このスクリプトは、ブロックを解放したり、inodeを変更したりすることなく、ファイルの既存のブロックの一部または全部をゼロにする方法を示しています。 statコマンドで実際のBLKSZとファイルサイズをキャプチャし、bash算術を使用してサイズを整数ブロックに丸める必要があるかもしれません。また、ddがファイルを拡張し、希少なデータを書き込むことを示します。

これは約100行の出力を生成するため、公開しません。良性です。ゼロ調整機能が重要です。

#! /bin/bash

FN='./Erase.data'
BLKSZ=4096

#.. Zeroise a specified range of blocks (zero-based).

Zero () {   #:: (from, to)

    dd 2>&1 ibs="${BLKSZ}" obs="${BLKSZ}" \
        seek="${1}" count="$(( $2 - $1 + 1 ))" \ 
        conv=notrunc if="/dev/zero" of="${FN}"
}

#.. Create a file of 8 * 4096B blocks, each labelled in every character.

Make () {   #:: (void)

    AWK='   
function Block (sz, id, Local, buf) {
    buf = sprintf ("%*s", sz, "");
    gsub (/./, id, buf);
    printf ("%s", buf);
}
{ for (f = 2; f <= NF; ++f) Block( $1, $(f)); }
'
    echo "${BLKSZ}" {A..H} | awk "${AWK}" > "${FN}" 
}

#.. Reveal the file.

Show () {

    echo; ls -l "${FN}"; stat "${FN}"; od -A d -t a "${FN}"; sleep 2 
}

#### Script Body Starts Here.

    #.. Make the file and prove its contents.
    Make > "${FN}" && Show 
    Zero 3 6 && Show 
    Zero 0 1 && Show 
    Zero 0 7 && Show 
    Zero 220 231 && Show 

これは本番バージョンの近似です。

#! /bin/bash

Usage () { expand -t 4 <<'EOF'

    Usage: ZeroAllBlocks [-h] [files ...]
        Warning: this command is as brutal as rm -f.
        -h: shows this message.

        Zeroises (binary zero) all blocks of all the files named.
        Sparse blocks will then consume real disk space.
EOF
}

#.. Zeroise a specified range of blocks (zero-based).

Zero () {   #:: (Fn, blksz, seek, count)

    local Fn="${1}" blksz="${2}" seek="${3}" count="${4}"

    dd status=none ibs="${blksz}" obs="${blksz}" \ 
        seek="${seek}" count="${count}" \
        conv=notrunc if="/dev/zero" of="${Fn}"
}

#.. Process a file.

File () {   #:: (filename)

    local Fn="${1}" szFile szBlock nBlock

    [[ -f "${Fn}" ]] || { printf '%s: No such file\n' "${Fn}"; return; }
    [[ -w "${Fn}" ]] || { printf '%s: Not writable\n' "${Fn}"; return; }
    read -r szFile szBlock <<<$( stat --printf='%s %o\n' "${Fn}" )
    nBlock="$(( (szFile + szBlock - 1) / szBlock ))"
    Zero "${Fn}" "${szBlock}" 0 "${nBlock}"
}

#### Script Body Starts Here.

    [[ "${1}" = "-h" ]] && { Usage; exit 2; }

    for Fn in "${@}"; do File "${Fn}"; done

答え3

これは、使用されるファイルシステムとストレージデバイスによって異なります。通常、生のフラッシュに最適化されたファイルシステムを使用しない限り、ファイルシステムはユーザーが指示したときに上書きされます。これらの特殊ファイルシステムはFSレベルで磨耗し、他の場所に書き込むことができます。

ただし、ストレージデバイスが通常のSATAまたはNVMe SSDの場合、内部で摩耗レベルが調整される可能性があり、実際の物理ストレージブロックは元のブロックデバイスに表示されるものとは異なる場合があります。したがって、ファイルシステムが間違いなく特定のブロックを上書きしていると思っても、「上書き」は別の物理的な場所で終わります。

ただし、SSDのウェアレベリングシステムを突破し、生のストレージを意味的に読み取るのはかなりの技術的障害であり、専門知識と特別なハードウェアツールが必要な場合があります。そして、SSDは、書き込みに使用できるブロックをできるだけ消去できるように、できるだけ早く「上書き」ブロックを先制的に消去できます。削除はしばしばSSDのパフォーマンスを制限する要因であるためです。

関連情報