Gzip으로 구성된 대량의 심볼릭 링크 파일

Gzip으로 구성된 대량의 심볼릭 링크 파일

많은 양의 심볼릭 링크 파일이 포함된 폴더가 있습니다. 이러한 파일은 각각 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하고 무슨 일이 일어나고 있는지 알아보는 것이 좋습니다.

관련 정보