다수의 심볼릭 링크 파일을 Gzip으로 압축

다수의 심볼릭 링크 파일을 Gzip으로 압축

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

관련 정보