Montar um sistema de arquivos somente leitura e redirecionar gravações para RAM?

21

É possível montar um arquivo de loopback como somente leitura e redirecionar todas as gravações para a RAM?

Mehrdad
fonte

Respostas:

18

É possível usar uma camada de sistema de arquivos de união como aufs .

Demo:

Criar uma imagem do sistema de arquivos

# dd if=/dev/zero of=/tmp/image bs=1024 count=1024
1024+0 records in
1024+0 records out
1048576 bytes (1.0 MB) copied, 0.0028428 s, 369 MB/s
# mke2fs /tmp/image 
...

Monte, preencha

# mkdir /tmp/imgmnt
# mount -o loop /tmp/image /tmp/imgmnt
# echo hello > /tmp/imgmnt/hello.txt
# umount /tmp/imgmnt

Monte-o somente leitura

# mount -o loop,ro /tmp/image /tmp/imgmnt
# echo blah > /tmp/imgmnt/hello.txt 
-su: /tmp/imgmnt/hello.txt: Read-only file system

Um pequeno sistema de arquivos RAM

# mkdir /tmp/rammnt
# mount -t tmpfs -o size=1M none /tmp/rammnt

Combine ambos

# mkdir /tmp/combined
# mount -t aufs -o br:/tmp/rammnt:/tmp/imgmnt=ro none /tmp/combined

Essa opção de montagem para criar uma nova "ramificação" ( br) empilhando /tmp/rammnt(leitura e gravação) em cima de /tmp/imgmnt(somente leitura). Este "ramo" é tornado visível como um sistema de arquivos (leitura / gravação) ativado /tmp/combined.

(Consulte a página do manual aufs (5) para todos os detalhes.)

Agora tudo o que está feito, eis o que você tem:

# ls /tmp/combined
hello.txt  lost+found
# cat /tmp/combined/hello.txt 
hello
# echo bye > /tmp/combined/hello.txt 
# cat /tmp/combined/hello.txt 
bye

# cat imgmnt/hello.txt 
hello
# cat rammnt/hello.txt 
bye

Portanto, as gravações "param" no tmpfssistema de arquivos e não tentam se propagar de volta ao arquivo de imagem montado em loop.

Você poderia ter usado um diretório simples (em um sistema de arquivos de leitura / gravação), ou possivelmente um diretório em /dev/shmse isso funcionar para você, em vez de criar um específico tmpfspara isso.


Esta técnica (ou variações) é usada por alguma distribuição LiveCD. A entrada aufs da Wikipedia lista alguns.

Esteira
fonte
+1 obrigado! Uma pergunta: (1) é possível fazer isso com fstab, de modo que o ponto de montagem seja /? (isto é, por isso o sistema é inicializado de uma imagem descartável, muito bonito.)
Mehrdad
Acho que não. Se você quiser fazer isso /, acredito que você está melhor com um initrd (é assim que é feito para os livecds que acredito). Você pode fazer isso a partir de um script init, embora isso pareça complicado.
Mat
8

Atualizar:

Parece que existem 2 outras maneiras mais simples de fazer isso no Ubuntu (pelo menos nas versões posteriores):

  1. sudo apt-get install overlayrootseguido por ajuste overlayroot="tmpfs:swap=1,recurse=0"em/etc/overlayroot.local.conf .

  2. sudo apt-get install fsprotectseguido passando fsprotectcomo um parâmetro do kernel


Eu finalmente descobri como fazer isso com o sistema de arquivos raiz (no Ubuntu 11.04)!

As etapas para tornar um sistema inicializável são simples. Eu usei este guia em combinação com este guia e várias pesquisas na web para descobrir como fazê-lo funcionar corretamente, sem erros.

Resumo:

  1. Corre:

    sudo apt-get install fsprotect apparmor-utils
    
  2. Salve isso em /etc/initramfs-tools/scripts/init-bottom/__rootaufs. Não acho que o nome realmente importe, mas o começo __pode ser usado para fins de pedidos; portanto, se você mudar o nome, poderá manter os sublinhados. (Esta é uma cópia deste arquivo .)

    #!/bin/sh -e
    
    case $1 in
      prereqs)
        exit 0
        ;;
    esac
    
    for x in $(cat /proc/cmdline); do
      case $x in
        root=*)
          ROOTNAME=${x#root=}
          ;;
        aufs=*)
          UNION=${x#aufs=}
        case $UNION in
          LABEL=*)
            UNION="/dev/disk/by-label/${UNION#LABEL=}"
            ;;
          UUID=*)
            UNION="/dev/disk/by-uuid/${UNION#UUID=}"
            ;;
        esac    
          ;;
      esac
    done
    
    if [ -z "$UNION" ]; then
        exit 0
    fi
    
    # make the mount points on the init root file system
    mkdir /aufs /ro /rw
    
    # mount read-write file system
    if [ "$UNION" = "tmpfs" ]; then
      mount -t tmpfs rw /rw -o noatime,mode=0755
    else
      mount $UNION /rw -o noatime
    fi
    
    # move real root out of the way
    mount --move ${rootmnt} /ro
    
    mount -t aufs aufs /aufs -o noatime,dirs=/rw:/ro=ro
    
    # test for mount points on union file system
    [ -d /aufs/ro ] || mkdir /aufs/ro
    [ -d /aufs/rw ] || mkdir /aufs/rw
    
    mount --move /ro /aufs/ro
    mount --move /rw /aufs/rw
    
    # strip fstab off of root partition
    grep -v $ROOTNAME /aufs/ro/etc/fstab > /aufs/etc/fstab
    
    mount --move /aufs /root
    
    exit 0
    
  3. Em /etc/default/grub, localize a linha que começa com GRUB_CMDLINE_LINUX_DEFAULT, e dentro das aspas que seguem, adicione o parâmetro aufs=tmpfs.

    Bônus: Se você precisar ocasionalmente desativar o redirecionamento temporariamente, basta remover este argumento da lista de parâmetros do kernel. Provavelmente, você pode fazer isso mantendo pressionada a tecla Shift quando o sistema está inicializando, para mostrar o menu GRUB; depois pressione e para editar os parâmetros e apenas apague o aufs=...parâmetro da lista.

  4. Acrescente essas linhas a /etc/sysctl.conf. ( Aviso : risco potencial à segurança.)

    kernel.yama.protected_nonaccess_hardlinks = 0
    kernel.yama.protected_sticky_symlinks = 0
    
  5. Execute estas linhas:

    sudo aa-complain dhclient3
    sudo chmod 0755 /etc/initramfs-tools/scripts/init-bottom/__rootaufs
    sudo update-initramfs -k all -u
    sudo update-grub
    

Se tudo correu bem, quando você reinicia, estará fazendo isso em um sistema de arquivos temporário. A parte da RAM estará em /rwe a imagem do disco estará em /ro, mas é claro que será somente leitura.

No entanto, se você inicializou em um sistema temporário, mas precisa fazer uma alteração permanente, poderá montar o /rosistema de arquivos dizendo

sudo mount -o remount,rw /ro

para torná-lo gravável e, em seguida, você pode fazer as modificações necessárias nesse diretório.

Mehrdad
fonte
2

Sim, por unionfs, consulte unionfs.filesystems.org . Você montou o primeiro sistema de arquivos somente leitura e como o segundo sistema de arquivos RAM de leitura e gravação através do unionfs.

No Ubuntu, você pode encontrar o pacote unionfs-fuse, que é outra implementação das mesmas coisas, mas no espaço do usuário, não como um módulo do kernel.

Jan Marek
fonte
0

Você também pode fazer isso no nível do dispositivo, sem uma união como aufs. Consulte mapeador de dispositivos snapshot-origin.

Tor Klingberg
fonte