많은 심볼릭 링크 파일이 포함된 폴더가 있습니다. 파일 크기는 모두 10-11GB입니다(특히 fastq 파일). 다양한 소스 폴더에서 가져오지만 심볼릭 링크 수준은 하나만 있도록 했습니다.
간단히 다음을 수행하여 압축하려고합니다.
gzip *.fastq
이로 인해 여러 가지 결과가 발생합니다.
too many levels of symbolic links
그러므로 실패했습니다.
그러나 내가 이렇게 하면:
for i in `ls | egrep *.fastq$`; do gzip -c $i > $i.gz; done;
실제로 작동한다. 내 질문은 간단합니다. 그들 사이의 차이점은 무엇입니까? AFAIK의 유일한 차이점은 두 번째 방법은 각 파일에 대해 새로운 gzip 프로세스를 시작하는 반면 첫 번째 방법은 하나의 프로세스에서 모든 작업을 수행해야 한다는 것입니다. gzip은 한 번에 하나의 심볼릭 링크 파일만 처리할 수 있나요? 일반 파일이 포함된 테스트 폴더에서 동일한 작업을 수행하면 양방향으로 작동합니다.
답변1
gzip 소스 코드(특히 Ubuntu 14.04에 포함된 gzip 1.6)를 빠르게 검사하면 관찰된 동작이 이 함수에서 비롯된 것임을 알 수 있습니다.공개 및 통계, gzip.c의 1037번째 줄에서 시작:
static int
open_and_stat (char *name, int flags, mode_t mode, struct stat *st)
{
int fd;
/* Refuse to follow symbolic links unless -c or -f. */
if (!to_stdout && !force)
{
if (HAVE_WORKING_O_NOFOLLOW)
flags |= O_NOFOLLOW;
else
{
#if HAVE_LSTAT || defined lstat
if (lstat (name, st) != 0)
return -1;
else if (S_ISLNK (st->st_mode))
{
errno = ELOOP;
return -1;
}
#endif
}
}
fd = OPEN (name, flags, mode);
if (0 <= fd && fstat (fd, st) != 0)
{
int e = errno;
close (fd);
errno = e;
return -1;
}
return fd;
}
주석 처리된 행에는 -c 또는 -f 플래그를 사용하여 호출되지 않는 한 gzip이 심볼릭 링크를 따르지 않으며 #if ... #endif 내에서 errno 변수가 ELOOP(심볼릭 링크가 너무 많이 발견됨)로 설정되어 있음을 나타냅니다. 압축할 파일은 실제로 심볼릭 링크입니다.
이제 gzip(1) 매뉴얼 페이지에서 -c 및 -f 플래그는 다음과 같습니다.
-c --stdout --to-stdout Write output on standard output; keep original files unchanged. If there are several input files, the output consists of a sequence of independently com‐ pressed members. To obtain better compression, concatenate all input files before compressing them. -f --force Force compression or decompression even if the file has multiple links or the corresponding file already exists, or if the compressed data is read from or written to a terminal. If the input data is not in a format recognized by gzip, and if the option --stdout is also given, copy the input data without change to the standard output: let zcat behave as cat. If -f is not given, and when not running in the background, gzip prompts to verify whether an existing file should be overwritten.
모든 것을 종합하고 원래 질문으로 돌아가면 다음과 같습니다.
- 첫 번째 예는 실제 심볼릭 링크를 압축하려고 시도하기 때문에 실패합니다.아니요실제 링크 루프)
- 두 번째는 -c 플래그를 사용하므로 원본 파일의 내용을 읽은 다음 압축된 출력을 stdout에 기록하므로 성공합니다.
- 세 번째 경우는 -c 대신 -f를 사용하는 것입니다. 이 경우 gzip은 심볼릭 링크를 압축하려고 할 때 불평하지 않지만 압축을 푼 후에는 다음과 같이 일반 파일이 됩니다.
$ls -l 총 4개 -rw-rw-r-- 1 x86tux x86tux 13 6월 16일 13:10 realfile.txt lrwxrwxrwx 1 x86tux x86tux 12 6월 16일 23:40 Symlink.txt -> realfile.txt $ gzip 심볼릭 링크.txt gzip: Symlink.txt: 심볼릭 링크 수준이 너무 많습니다. $ gzip -f 심볼릭 링크.txt $ls -l 총 8개 -rw-rw-r-- 1 x86tux x86tux 13 6월 16일 13:10 realfile.txt -rw-rw-r-- 1 x86tux x86tux 45 6월 16일 13:10 symlink.txt.gz $gunzip 심볼릭 link.txt.gz $ls -l 총 8개 -rw-rw-r-- 1 x86tux x86tux 13 6월 16일 13:10 realfile.txt -rw-rw-r-- 1 x86tux x86tux 13 6월 16일 13:10 Symlink.txt $md5sum* 618f486e0225d305d16d0648ed44b1eb 실제 파일.txt 618f486e0225d305d16d0648ed44b1eb 심볼릭 링크.txt
답변2
파일당 단일 프로세스가 작업을 방해할 수 있다면 약간의 해를 끼칠 수 있지만 10-11GB에서는 exec
진행이 방해받는 시나리오를 상상하기 어렵습니다 gzip
.
마찬가지로 작은 파일 묶음인 경우 gzip
각 파일의 비교할 데이터가 적기 때문에 압축할 수 없을 가능성이 높지만 압축 작업당 10-11GB를 사용하면 압축이 불가능합니다. 이슈.
오류의 원인을 알아내는 것이 흥미로울 것이라고 생각했습니다. lsof
배경 PID에 적용 gzip
하고 무슨 일이 일어나고 있는지 알아보는 것이 좋습니다.