Respostas:
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"
Você pode garantir que um arquivo seja excluído quando o script sair (incluindo mortes e falhas), abrindo um descritor de arquivo e excluindo-o. O arquivo permanece disponível (para o script; não para outros processos, mas /proc/$PID/fd/$FD
é uma solução alternativa), desde que o descritor de arquivo esteja aberto. Quando é fechado (o que o kernel faz automaticamente quando o processo termina), o sistema de arquivos exclui o arquivo.
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
exec 3>"$tmpfile"
rm "$tmpfile"
: ...
echo foo >&3
/proc
- exceto para sistemas que não o possuem.
exec 3> "$tmpfile"
faz? Isso não é útil apenas se o tmpfile for um script independente?
cat <&3
vai dar Bad file descriptor
. Eu apreciaria se você consertar ou remover; desinformação não ajuda muito.
Use mktemp
para criar um arquivo ou diretório temporário:
temp_file=$(mktemp)
Ou para um direcotry:
temp_dir=$(mktemp -d)
No final do script, você deve excluir o arquivo / diretório temporário:
rm ${temp_file}
rm -R ${temp_dir}
mktemp cria um arquivo no /tmp
diretório ou no diretório fornecido com o --tmpdir
argumento
trap "rm -f $temp_file" 0 2 3 15
logo após criar o arquivo para que, quando o script sair ou for interrompido, ctrl-C
o arquivo ainda seja removido.
EXIT
for o único gancho trap
?
kill -9 $somepid
. Esse sinal de matança em particular é a morte instantânea e nada mais acontece.
bash -c 'echo $$; trap "echo foo" 0; sleep 5'
EXIT
é suficiente.
Se você estiver no sistema que possui mktemp , use-o como outras respostas.
Com o suporte de ferramenta POSIX:
umask 0177
tmpfile=/tmp/"$0"."$$"."$(awk 'BEGIN {srand();printf "%d\n", rand() * 10^10}')"
trap 'rm -f -- "$tmpfile"' INT TERM HUP EXIT
: > "$tmpfile"
EXIT
for o único gancho trap
?
tmpfile
ainda será removido antes da saída do script, mas não quando o script receber outros sinais.
That's not what happens
?
mktemp
originado no HP / UX com uma sintaxe diferente. Todd C. Miller criou um diferente para o OpenBSD em meados dos anos 90 (copiado pelo FreeBSD e NetBSD) e posteriormente o disponibilizou como um utilitário independente (www.mktemp.org). Esse é o que normalmente era usado no Linux até que um mktemp
utilitário (principalmente compatível) foi adicionado aos coreutils do GNU em 2007. Apenas para dizer que não se pode realmente dizer que mktemp
é um utilitário do GNU.
Algumas conchas têm o recurso embutido.
zsh
A =(...)
forma de substituição do processo usa um arquivo temporário. Por exemplo, =(echo test)
expande para o caminho de um arquivo temporário que contém test\n
.
$ {cat $file; ls -l /dev/fd/3; echo test2 >&3; cat $file} 3<> ${file::==(echo test)}
test
lrwx------ 1 stephane stephane 64 Jan 30 11:19 /dev/fd/3 -> /tmp/zshMLbER0
test2
Esse arquivo é removido automaticamente quando o comando é concluído.
Here-files ou here-strings bash
e zsh
são implementados como arquivos temporários excluídos.
Então, se você fizer:
exec 3<<< test
O descritor de arquivo 3 está conectado a um arquivo temporário excluído que contém test\n
.
Você pode obter seu conteúdo com:
cat <&3
Se no Linux, você também pode ler ou gravar nesse arquivo via /dev/fd/3
$ exec 3<<< test
$ cat <&3
test
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo
(algumas outras conchas usam tubos ou podem ser usadas /dev/null
se o documento aqui estiver vazio).
Não há mktemp
utilitário POSIX. No entanto, o POSIX especifica uma mkstemp(template)
API C e o m4
utilitário padrão expõe essa API com a mkstemp()
função m4 com o mesmo nome.
mkstemp()
fornece um nome de arquivo com uma parte aleatória que foi garantida para não existir no momento em que a função foi chamada. Ele cria o arquivo com permissões 0600 de forma livre de corrida.
Então, você poderia fazer:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
Observe, no entanto, que você precisa lidar com a limpeza na saída, embora, se você apenas precise escrever e ler o arquivo um número fixo de vezes, poderá abri-lo e excluí-lo logo após criar o arquivo para aqui-doc / aqui- abordagem de string acima:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
# open once for writing, twice for reading:
exec 3> "$tempfile" 4< "$tempfile" 5< "$tempfile"
rm -f -- "$tmpfile"
cmd >&3 # store something in the temp file
exec 3>&- # fd no longer needed
# read the content twice:
cat <&4
cat <&5
Você pode abrir o arquivo para leitura uma vez e retroceder entre duas leituras, no entanto, não existe um utilitário POSIX que possa fazer isso retroceder ( lseek()
); portanto, não é possível fazê-lo de forma portável em um script POSIX ( zsh
( sysseek
incorporado) e ksh93
( <#((...))
operador) pode faça isso).
<()
=(...)
.
Aqui está uma resposta um pouco melhorada na linha de Hauke Laging:
#!/bin/bash
tmpfile=$(mktemp) # Create a temporal file in the default temporal folder of the system
# Lets do some magic for the tmpfile to be removed when this script ends, even if it crashes
exec {FD_W}>"$tmpfile" # Create file descriptor for writing, using first number available
exec {FD_R}<"$tmpfile" # Create file descriptor for reading, using first number available
rm "$tmpfile" # Delete the file, but file descriptors keep available for this script
# Now it is possible to work with the temporal file
echo foo >&$FD_W
echo bar >&$FD_W # Note that file descriptor always concatenates, not overwrites
cat <&$FD_R
Meu fluxo de trabalho normalmente com arquivos temporários é devido a algum script bash que estou testando. Eu quero fazer tee
isso para que eu possa ver que está funcionando e salvar a saída para a próxima iteração do meu processo. Eu criei um arquivo chamadotmp
#!/bin/bash
echo $(mktemp /tmp/$(date +"%Y-%m-%d_%T_XXXXXX"))
para que eu possa usá-lo como
$ some_command --with --lots --of --stuff | tee $(tmp)
A razão pela qual eu gosto da data e hora formatada antes dos valores aleatórios é que me permite encontrar o arquivo tmp que acabei de criar com facilidade, e não preciso pensar em como nomeá-lo na próxima vez (e focar apenas em obter meu script dang trabalhar).