ෂෙල් ස්ක්‍රිප්ටයේ තාවකාලික ගොනුවක් සාදන්නේ කෙසේද?


182

ස්ක්‍රිප්ට් එකක් ධාවනය කරන අතරතුර, /tmpඩිරෙක්ටරියේ තාවකාලික ගොනුවක් සෑදීමට මට අවශ්‍යය .

එම ස්ක්‍රිප්ට් එක ක්‍රියාත්මක කිරීමෙන් පසුව එය එම ස්ක්‍රිප්ට් එකෙන් පිරිසිදු වේ.

ෂෙල් ස්ක්‍රිප්ට් වලින් එය කරන්නේ කෙසේද?

Answers:


227
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"

ස්ක්‍රිප්ට් පිටවන විට (ills ාතන හා බිඳ වැටීම් ඇතුළුව) ගොනුවක් මකාදැමීමට වග බලා ගත හැකිය. /proc/$PID/fd/$FDලිපිගොනු විස්තරය විවෘතව පවතින තාක් කල් ගොනුව ලබා ගත හැකිය (ස්ක්‍රිප්ට් සඳහා; ඇත්ත වශයෙන්ම වෙනත් ක්‍රියාදාමයන් සඳහා නොව එය ක්‍රියාත්මක වේ). එය වසා දැමූ විට (ක්‍රියාවලිය පිටවන විට කර්නලය ස්වයංක්‍රීයව කරයි) ගොනු පද්ධතිය ගොනුව මකා දමයි.

tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
exec 3>"$tmpfile"
rm "$tmpfile"
: ...
echo foo >&3

4
හොඳ පිළිතුරක්, කඩාවැටීමකදී ලිපිගොනු විස්තරය සමඟ අලංකාර විසඳුමක් +1
අවුල්සහගත

2
/proc- එය නොමැති පද්ධති හැර.
වැඩිදුර දැනුම් දෙන තුරු විරාමය.

7
මොකද කරන්නේ exec 3> "$tmpfile"? Tmpfile තනිවම ලියවිල්ලක් නම් පමණක් එය ප්‍රයෝජනවත් නොවේද?
ඇලෙක්සෙජ් මගුරා

5
සාදන ලද FD වෙතින් ඔබ කියවන්නේ කෙසේද?
eckes

3
"ඔබට පූසා <3 හෝ ඊට සමාන දෙයක් භාවිතා කළ හැකිය." ඇත්ත වශයෙන්ම එය 3 @ dragon788 නම් ගොනුවකින් කියවනු ලැබේ. එසේම, cat <&3ලබා දෙනු Bad file descriptorඇත. ඔබ එය නිවැරදි කළහොත් හෝ ඉවත් කළහොත් මම එය අගය කරමි. වැරදි තොරතුරු බොහෝ සෙයින් උපකාරී නොවේ.
ඩැනියෙල් ෆැරල්

72

mktempතාවකාලික ගොනුවක් සෑදීමට භාවිතා කරන්න

temp_file=$(mktemp)

හෝ, තාවකාලික නාමාවලියක් නිර්මාණය කිරීමට :

temp_dir=$(mktemp -d)

ස්ක්‍රිප්ට් එක අවසානයේ ඔබට තාවකාලික ගොනුව හෝ නාමාවලිය මකා දැමිය යුතුය

rm ${temp_file}
rm -R ${temp_dir}

mktempගොනුව /tmpබහලුම තුළ හෝ --tmpdirතර්කය සමඟ ලබා දී ඇති නාමාවලියෙහි සාදයි .


21
trap "rm -f $temp_file" 0 2 3 15ගොනුව සෑදූ විගසම ඔබට භාවිතා කළ හැකි වන අතර එමඟින් පිටපත පිටවන විට හෝ ctrl-Cගොනුව සමඟ නතර වූ විට එය ඉවත් කරනු ලැබේ.
වර්ටෙල්

1
urtwurtel EXITඑකම කොක්කක් නම් කුමක් සිදුවේද trap?
හෝක් ලේජින්

4
AuHaukeLaging එවිට Ctrl + C සමඟ ස්ක්‍රිප්ට් එක නැවැත්වුවහොත් උගුලට වෙඩි තබන්නේ නැත. සැලකිල්ලට ගත යුතු කරුණක් නම් ඔබ නම් TRAP උදව් නොකරන බවයි kill -9 $somepid. එම විශේෂිත kill ාතන සං signal ාව යනු වෙන කිසිවක් සිදු නොවන ක්ෂණික මරණයයි.
dragon788

5
@ dragon788 ඔබ එය උත්සාහ කර තිබේද? ඔයා කළ යුතුයි. bash -c 'echo $$; trap "echo foo" 0; sleep 5'
Hauke ​​Laging

උගුලට හසු EXITවීම ප්රමාණවත්ය.
කුසලනන්ද

17

සමහර ෂෙල් වෙඩි වල අංගයක් ඇත.

zsh

zsh'S =(...)ක්රියාවලිය ආදේශ ආකාරයක තාවකාලික ගොනුවක් භාවිතා කරයි. උදාහරණයක් ලෙස =(echo test)අඩංගු තාවකාලික ගොනුවක මාවත දක්වා විහිදේ 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

විධානය අවසන් වූ පසු එම ගොනුව ස්වයංක්‍රීයව ඉවත් වේ.

ලිනක්ස් හි bash / zsh.

මෙන්න-ගොනු හෝ මෙහි-නූල් දී bashහා zshමකා දමන තාවකාලික ගොනු ලෙස ක්රියාත්මක කරනු ලැබේ.

එබැවින් ඔබ එසේ කරන්නේ නම්:

exec 3<<< test

ලිපිගොනු 3 විස්තර කර ඇති තාවකාලික ගොනුවකට සම්බන්ධ කර ඇත test\n.

ඔබට එහි අන්තර්ගතය ලබා ගත හැක්කේ:

cat <&3

ලිනක්ස් හි තිබේ නම්, ඔබට එම ගොනුව කියවීමට හෝ ලිවීමට හැකිය /dev/fd/3, බාෂ් අනුවාදය 5 සහ ඊට ඉහළින් වුවද, ඔබට මුලින්ම එයට ලිඛිත අවසරයන් යථා තත්වයට පත් කිරීමට අවශ්‍ය වනු ඇත (එම බැෂ් දැන් පැහැදිලිවම ඉවත් කරයි):

$ exec 3<<< test
$ cat <&3
test
$ chmod u+w /dev/fd/3 # only needed in bash 5+
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo

(වෙනත් ෂෙල් වෙඩි පයිප්ප භාවිතා කරයි, නැතහොත් /dev/nullමෙහි ලේඛනය හිස් නම් භාවිතා කළ හැකිය ).

පොසික්ස්

mktempPOSIX උපයෝගීතාවයක් නොමැත . POSIX කෙසේ වෙතත් mkstemp(template)C API එකක් නියම කරන අතර m4සම්මත උපයෝගීතාව එම API එක mkstemp()m4 ශ්‍රිතය සමඟ එකම නමින් නිරාවරණය කරයි .

mkstemp()ශ්‍රිතය හැඳින්වූ අවස්ථාවේ නොපවතින බවට සහතික වූ අහඹු කොටසක් සහිත ගොනු නාමයක් ඔබට ලබා දෙයි. එය 0600 අවසරයකින් යුත් ගොනුව තරඟ රහිත ආකාරයකින් නිර්මාණය කරයි.

ඉතින්, ඔබට කළ හැකිය:

tmpfile=$(
  echo 'mkstemp(template)' |
    m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit

කෙසේ වෙතත්, පිටවීමේදී පිරිසිදු කිරීම හැසිරවිය යුතු බව සලකන්න, ඔබට ගොනුව ස්ථාවර වාර ගණනක් ලිවීමට හා කියවීමට අවශ්‍ය නම්, ඔබට එය විවෘත කර මකා දැමිය හැකිය. ඉහත සංගීත ප්‍රවේශය:

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

ඔබට කියවීම සඳහා ගොනුව එක් වරක් විවෘත කළ හැකි අතර කියවීම් දෙකක් අතර පෙරළා දැමිය හැකිය, කෙසේ වෙතත් එම පෙරළීම ( lseek()) කළ හැකි POSIX උපයෝගීතාවයක් නොමැත , එබැවින් ඔබට එය POSIX ස්ක්‍රිප්ටයකින් ( zsh( sysseekබිල්ඩින්) සහ ksh93( <#((...))ක්‍රියාකරු) කළ හැකිය. එය කරන්න).


1
බෑෂ් ද භාවිතා ක්රියාවලිය ආදේශන ඇත<()
WinnieNicklaus

4
Inn වින්නි ​​නික්ලෝස්, ඔව්, නමුත් එය තාවකාලික ලිපිගොනු භාවිතා නොකරන බැවින් මෙහි අදාල නොවේ. ක්‍රියාවලි ආදේශනය ksh විසින් හඳුන්වා දෙන ලද අතර එය bash සහ zsh මගින් පිටපත් කරන ලද අතර zsh එය 3 වන ස්වරූපයෙන් දීර් extended කළේය : =(...).
ස්ටෙෆාන් චසෙලාස්

16

ඔබ mktemp ඇති පද්ධතියේ සිටී නම් , ඔබ එය වෙනත් පිළිතුරු ලෙස භාවිතා කළ යුතුය.

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එකම කොක්කක් නම් කුමක් සිදුවේද trap?
හෝක් ලේජින්

Au හවුක්ලජින්: tmpfileස්ක්‍රිප්ට් පිටවීමට පෙර තවමත් ඉවත් කරන්න, නමුත් ස්ක්‍රිප්ටයට වෙනත් සං als ා ලැබුණු විට නොවේ.
cuonglm

මෙහි සිදු වන්නේ එය නොවේ (GNU bash, වෙළුම 4.2.53).
හෝක් ලේජින්

1
Au හක්ලෙජින්: ඔබ අදහස් කළේ That's not what happensකුමක්ද?
cuonglm

4
mktempHP / UX හි ආරම්භ වූයේ වෙනස් වාක්‍ය ඛණ්ඩයකි. ටොඩ් සී. මිලර් 90 දශකයේ මැද භාගයේදී OpenBSD සඳහා වෙනස් එකක් නිර්මාණය කළේය (FreeBSD සහ NetBSD විසින් පිටපත් කරන ලදි) පසුව එය ස්වාධීන උපයෝගීතාවයක් ලෙස (www.mktemp.org) ලබා ගත හැකි විය. mktemp2007 දී (බොහෝ දුරට අනුකූල) උපයෝගීතාවයක් GNU coreutils වෙත එකතු කරන තෙක් ලිනක්ස් හි සාමාන්‍යයෙන් භාවිතා වූයේ එයයි. කෙනෙකුට ඇත්ත වශයෙන්ම කිව නොහැකි mktempනම් GNU උපයෝගීතාවයකි.
ස්ටෙෆාන් චසෙලාස්

7

හෝක් ලේජින්ගේ පේළියේ ටිකක් වැඩිදියුණු කළ පිළිතුර මෙන්න:

#!/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

2
අන්තර්ගතය ලබා ගත හැක්කේ එක් වරක් පමණක් බව සැලකිල්ලට ගත යුතුය. එනම්, මම දෙවන වරට කැට් <& $ FD_R කළහොත්, ප්‍රතිදානයක් නිපදවන්නේ නැත. Unix.stackexchange.com/questions/166482/… බලන්න . වැඩසටහන බිඳ වැටුණත් ගොනුව ස්වයංක්‍රීයව මකා දැමීමට ක්‍රමයක් තිබේද?
smihael

0

සාමාන්‍යයෙන් තාවකාලික ලිපිගොනු සමඟ මගේ කාර්ය ප්‍රවාහය සිදුවන්නේ මා පරීක්ෂා කරන සමහර බාෂ් ස්ක්‍රිප්ට් නිසාය. මට teeඑය ඉහළ නැංවීමට අවශ්‍ය නිසා එය ක්‍රියාත්මක වන බව දැක මගේ ක්‍රියාවලියේ ඊළඟ ක්‍රියාකාරීත්වය සඳහා ප්‍රතිදානය සුරකිනු ඇත. මම ගොනුවක් නිර්මාණය කළාtmp

#!/bin/bash
echo $(mktemp /tmp/$(date +"%Y-%m-%d_%T_XXXXXX"))

ඒ නිසා මට එය භාවිතා කළ හැකිය

$ some_command --with --lots --of --stuff | tee $(tmp)

අහඹු අගයන්ට පෙර ආකෘතිකරණය කර ඇති දිවා කාලයට මා කැමති වීමට හේතුව එය මා විසින් පහසුවෙන්ම සාදන ලද tmp ගොනුව සොයා ගැනීමට ඉඩ සලසන අතර ඊළඟ වතාවේ එය නම් කළ යුත්තේ කුමක් ද යන්න ගැන සිතා බැලිය යුතු නැත (සහ මගේ ඩැං ස්ක්‍රිප්ට් ලබා ගැනීම කෙරෙහි අවධානය යොමු කරන්න වැඩට).

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.