Como criar um arquivo temporário na RAM?

29

Eu tenho um script que canalizará sua saída para |tee scriptnameYYMMDD.txt. Após cada ciclo do loop for no qual a saída é gerada, estarei revertendo o conteúdo do arquivo tac scriptnameYYYYMMDD.txt > /var/www/html/logs/scriptname.txtpara que a saída do log fique visível em uma janela do navegador com as linhas mais recentes na parte superior.

Vou ter vários scripts fazendo isso em paralelo. Estou tentando minimizar a atividade do disco, para que a saída de |tee scriptnameYYYYMMDD.txtum disco RAM seja melhor. mktempcria um arquivo na /tmppasta, mas isso não parece estar fora do disco.

user208145
fonte
Precisa ser um ramfs ou um tmpfs (o segundo é melhor). Verifique se um desses fs já está montado no seu sistema; se sim, você pode usá-lo. Se não, você precisa montá-lo.
peterh diz restabelecer Monica
Eu atualizar fstaba fim de montar um tmpfssobre /tmpe em seguida, reiniciar a máquina.
kasperd
11
você pode considerar incrementalmente tailos arquivos (ou iniciá-lo via CGI mediante solicitação ou algo assim), em vez de tacfazer a coisa toda.
mikeserv
Isso parece funcionar no teste (desculpe pela formatação diminuída): TEMPPATH="/ramdisk" LOGPATH="/var/www/html/log" ... echo <various calls to echo> | tee -a $TEMPPATH/moveKRT$(date '+%Y%m%d').txt ... no final do loop for, cp $TEMPPATH/moveKRT$(date '+%Y%m%d').txt $LOGPATH/moveKRT$(date '+%Y%m%d').txt tac $TEMPPATH/moveKRT$(date '+%Y%m%d').txt > $LOGPATH/moveKRT.txt estou ciente da possibilidade minúscula de que a alteração de 23: 59: 59.999 para 00:00: 00 pode afetar alguns arquivos, mas a chance é aceitável.
user208145
Atualização sobre o meu progresso nisso: Eu tenho um volume tmpfs de 1 GB montado em / ramdisk. Tenho arquivos entrando nas pastas pessoais do usuário via FTP. Eles são movidos para uma subpasta / ramdisk / queues / xyz / para processar e são excluídos posteriormente. Na inicialização, eu tenho um script que recria minha estrutura de diretório necessária em / ramdisk. Isso deve resultar em atividade mínima do disco para os arquivos recebidos. Até o momento, a única outra maneira de reduzir a E / S de disco para esses scripts seria criar essas pastas de usuário em um tmpfs criado na inicialização, antes que qualquer arquivo entre via FTP nessas pastas de usuário. Obrigado a todos.
user208145

Respostas:

22

Você pode montar uma tmpfspartição e escrever o arquivo lá:

mount -t tmpfs -o size=500m tmpfs /mountpoint

Esta partição agora está limitada a 500 MB. Se o seu arquivo temporário cresce maior do que 500 MB ocorrerá um erro: no space left on device. Porém, não importa quando você especificar uma quantidade maior de espaço do que a RAM do sistema. tmpfstambém usa espaço de troca, portanto, não é possível forçar uma falha no sistema ramfs.

Agora você pode gravar seu arquivo em /mountpoint:

command | tee /mountpoint/scriptnameYYYYMMDD.txt
caos
fonte
3
size=[num]%também é bom - um tmpfs pode ser limitado a uma porcentagem da memória disponível. Geralmente é mais fácil assim se os comandos nem sempre são direcionados para a mesma máquina (real / virtual) . Também é útil que um tmpfs não descarte conteúdo com -o remount,size=newsize.
mikeserv
11
Como a pergunta gira em torno de um script bash, que não temos motivos para supor que seja executado pela raiz, você pode especificar se é possível mountevitar que usuários não-root usem -tou -o? Ou seja, como é possível criar scripts que usem tmpfs(ou RAM de qualquer outra maneira) para salvar operações no disco, se um sistema de arquivos adequado ainda não existir no sistema?
Jonathan Y.
Não é uma boa resposta. Falhará se você não for root.
Alex4
11

Tente isso com o Ubuntu:

ramtmp="$(mktemp -p /dev/shm/)"
tac scriptnameYYYYMMDD.txt > "$ramtmp"
Cyrus
fonte
3
quão estável está escrevendo /run/shm/? Posso aplicar chmodalterações no arquivo temporário, se necessário? Notei que os bits do modo da pasta são idênticos à /tmppasta. obrigado.
user208145
11
Como em outros diretórios, os arquivos gerados em /run/shm(link simbólico para /dev/shm) mktemptambém possuem uma permissão padrão de -rw-------(600) e você pode alterá-la se necessário sudo chmod.
KrisWebDev #
9

A resposta a seguir foi descoberta ao investigar as respostas anteriores e as informações nesta pergunta aqui e não teriam sido encontradas sem elas. Cudos para eles.

No meu sistema linuxmint (e eu assumiria a maioria dos sistemas baseados em ubuntu e possivelmente também em debian), existe um usuário de propriedade tmpfs montado automaticamente no /run/user/1000/

Use df -Tpara verificar.

11:41:11 jesse @ Limbo: ~ $ df -T
Blocos de tipo 1K do sistema de arquivos Usado Disponível Disponível% Montado em
udev devtmpfs 15904812 4 15904808 1% / dev
tmpfs tmpfs 3184120 1700 3182420 1% / corrida
/ dev / sdb2 ext4 14248880 11464788 2037240 85% /
nenhum tmpfs 4 0 4 0% / sys / fs / cgroup
nenhum tmpfs 5120 0 5120 0% / execução / bloqueio
nenhum tmpfs 15920584 848 15919736 1% / execução / shm
nenhum tmpfs 102400 12 102388 1% / execução / usuário
/ dev / sdb3 ext4 100861352 90755700 4959136 95% / mnt / data

Abaixo, /run/user/há um diretório para cada usuário normal no sistema

12:07:35 jesse@Limbo:~$ ls -l /run/user
total 0
drwx------ 2 root  root   40 Aug  7 09:50 0
drwx------ 8 jesse jesse 180 Aug  7 11:38 1000

Esses diretórios são nomeados após os respectivos IDs de usuário. Podemos obter o ID do usuário para id -uver man iddetalhes sobre este comando.

12:07:43 jesse@Limbo:~$ ls -l /run/user/$(id -u)
total 0
drwx------ 2 jesse jesse  60 Aug  7 09:50 dconf
dr-x------ 2 jesse jesse   0 Aug  7 09:50 gvfs
drwx------ 2 jesse jesse  80 Aug  7 09:50 pulse
lrwxrwxrwx 1 root  root   17 Aug  7 09:50 X11-display -> /tmp/.X11-unix/X0

Em seguida, podemos usar o mktempcomando com a --tmpdiropção de criar arquivos e diretórios temporários neste sistema de arquivos temporários, criando assim arquivos temporários na RAM.

Seguindo as orientações fornecidas aqui , primeiro criei um diretório temporário e depois criei meus arquivos temporários:

mydir=$(mktemp -dt "$(basename $0).XXXXXXXX" --tmpdir=/run/user/$(id -u))

para criar um diretório temporário /run/user/1000/bash.w42BYxbG/, em seguida,

myfile=$(mktemp -t "$(basename $0).XXXXXXXX" --tmpdir=$mydir)

para criar um arquivo temporário nele.

Isso facilita a limpeza desses arquivos, pois tudo o que preciso fazer é rm -r $mydir.

Por padrão, todos esses arquivos são de propriedade e legíveis apenas pelo usuário que os criou.

Nota: A $(basename $0)parte do comando extrai o nome do script / processo que executou o mktemp. Se eu tiver um script /home/jesse/scripts/myScript.sh, $(basename $0)retornará myScript.shquando executado por este script. Assim, os comandos acima criariam /run/user/1000/myScript.sh.w42BYxbG/e /run/user/1000/myScript.sh.w42BYxbG/myScript.sh.BCzSmq06respectivamente.

Jesse, o Andarilho do Vento
fonte
/run/user/1000está disponível em cada linux que usa systemd, portanto não está disponível apenas em sistemas baseados em debian, mas também na maioria das outras distribuições de linux. Caso contrário, / tmp deve ser usado. Você pode simplificar seus comandos usando a variável $ XDG_RUNTIME_DIR, que já mantém o diretório correto para cada usuário. Para obter mais informações, verifique, por exemplo, esta resposta: unix.stackexchange.com/questions/162900/… #
Alex Alex
11
Use mkstemp sobre mktemp !! Razão de: linux.die.net/man/3/mktemp : na seção Bugs "... todo uso de mktemp () é um risco à segurança, a corrida é evitada pelo mkstemp (3)."
Alex #
0

Pelo que entendi, os objetivos são: (1) não armazenar o arquivo invertido para o disco, para ser servido para o navegador (nota: este poderia ser tmpfs, etc, como todas as outras respostas já detalhe); mas (2) evite gravar o primeiro arquivo tmp no disco, com a saída original; e, no entanto, (3) ainda exibe a saída original para stdout.

Nesse caso, o seguinte pode atender às suas necessidades, usando a substituição do processo bash (ou seja, basicamente um pipe nomeado):

command | tee >( tac > /var/www/html/logs/scriptname.txt )

Observe que isso está imprimindo continuamente a saída no stdout e, quando o comando termina (quando o loop termina), reverte essa saída e a grava no arquivo de saída. Ilustrado através do seguinte, que imprime uma linha por segundo e, após o término, o arquivo /tmp/foo.txtcontém as linhas invertidas:

i=0
while [ $i -lt 10 ]; do
    ((i = i+1))
    echo "==$i== $(date)"
    sleep 1
done | tee >( tac >> /tmp/foo.txt ) 
Michael
fonte