많은 양의 심볼릭 링크 파일이 포함된 폴더가 있습니다. 이러한 파일은 각각 10-11GB 정도입니다(구체적으로는 fastq 파일). 다양한 소스 폴더에서 가져오지만 심볼릭 링크 수준은 하나만 있는지 확인했습니다.
간단히 다음을 수행하여 gzip으로 압축하려고합니다.
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)를 빠르게 확인하면 관찰된 동작이 다음 함수에서 비롯된 것임을 알 수 있습니다.open_and_stat, 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;
}
주석 행에는 gzip이 -c 또는 -f 플래그와 함께 호출되지 않는 한 심볼릭 링크를 따르지 않으며 #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 6월 16일 13일 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 6월 16일 13일 13:10 realfile.txt -rw-rw-r-- 1 x86tux x86tux 45 6월 16일 13:10 symlink.txt.gz $ gunzip symlink.txt.gz $ ls -l 총 8개 -rw-rw-r-- 1 x86tux x86tux 6월 16일 13일 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
하고 무슨 일이 일어나고 있는지 알아보는 것이 좋습니다.