그것이 a
존재하고 내가 들어가면
cp /dev/zero a
이전 콘텐츠를 덮어쓸 수 있습니까 a
? 아니면 단순히 다음과 같은 내용을 얻을 수 있습니까?
rm a
cp /dev/zero a
추신. 이것이 파일을 안전하게 삭제하는 올바른 방법이라고 말하는 것은 아닙니다. 단지 특정 명령의 효과가 궁금할 뿐입니다.
답변1
/dev/zero
파일에 복사하는 이유는 무엇입니까 ?
안전하게 삭제하시겠습니까
a
? 그렇다면cp
잘못된 도구가 있습니다.shred
하드 드라이브를 사용하고 있는지,fstrim
SSD를 사용하고 있는지 확인하세요 . (내가 모르는 다른 도구가 있을 수 있으므로 Google에서 "안전한 제거"를 검색해 보는 것이 좋습니다.)무한을 이해하시나요
/dev/zero
? 0을 무한정 반환하므로cp
포함하는 파일 시스템이 가득 찰a
때까지 완료되지 않습니다 .그러나
cp
희소 파일 감지의 일부로 모두 0인 페이지 쓰기가 억제되기 때문에 이런 일은 결코 발생하지 않을 수 있습니다.모두 0으로 지정된 크기의 파일을 생성하시겠습니까?
cp
여전히 잘못된 도구입니다.dd
에서 복사할 바이트 수를 지정하려면 를 사용해야 합니다/dev/zero
.
일반적으로 cp
일반 파일을 다른 일반 파일로 복사할 때 관심 있는 것은 복사본이 논리적으로 동일하다는 것뿐입니다.
장치 파일을 사용 중이거나 원시 파일 블록이 처리되는 방법을 제어하려는 경우 다른 프로그램을 사용해야 합니다.
답변2
나는 당신이 파일을 열고 처음부터 쓸 때 기존의 모든 블록이 즉시 해제되고(여전히 기존 내용을 포함하고 있음) cp가 제로 패딩을 위한 새 블록을 얻게 될 것이라고 생각합니다.
또한 파일은 전체 파티션을 채울 때까지 확장됩니다. 즉, 원래 크기는 유지되지 않습니다.
이 명령 에는 stat를 사용하여 원래 크기를 찾고, 이를 전체 블록으로 반올림하고, 및 옵션을 사용하여 0의 크기를 원래 블록과 동일한 크기로 조정할 수 있는 dd
옵션이 있습니다 .conv=notrunc
count
bs
편집: 쉘 > 리디렉션이 동일한 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를 변경하지 않고 파일의 기존 블록 일부 또는 전부를 0으로 만드는 방법을 보여줍니다. 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 성능을 제한하는 요소이기 때문입니다.