শেল স্ক্রিপ্টে অস্থায়ী ফাইল কীভাবে তৈরি করবেন?


155

স্ক্রিপ্ট চালানোর সময়, আমি /tmpডিরেক্টরিতে একটি অস্থায়ী ফাইল তৈরি করতে চাই ।

Script স্ক্রিপ্টটি কার্যকর করার পরে, এটি script স্ক্রিপ্ট দ্বারা পরিষ্কার করা হবে।

কিভাবে এটি শেল স্ক্রিপ্টে করবেন?

উত্তর:


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

আপনি নিশ্চিত করতে পারেন যে স্ক্রিপ্টগুলি প্রস্থান (কিল এবং ক্র্যাশ সহ) ফাইল থেকে একটি ফাইল বর্ণনাকারী খোলার মাধ্যমে এবং মুছে ফেলা হলে কোনও ফাইল মুছে ফেলা হবে। /proc/$PID/fd/$FDযতক্ষণ না ফাইল বর্ণনাকারী খোলা থাকে ততক্ষণ ফাইলটি (স্ক্রিপ্টের জন্য; অন্য প্রক্রিয়াগুলির জন্য না, তবে একটি কার্যক্ষম) is এটি বন্ধ হয়ে গেলে (প্রক্রিয়াটি শেষ হয়ে গেলে কার্নেলটি স্বয়ংক্রিয়ভাবে কাজ করে) ফাইল সিস্টেমটি ফাইলটি মুছে দেয়।

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

4
ভাল উত্তর, ক্র্যাশ +1 ফাইলের ক্ষেত্রে ফাইল বর্ণনাকারীর সাথে মার্জিত সমাধান
বিশৃঙ্খলা

2
/proc- এমন সিস্টেমে ব্যতীত যেগুলি নেই।
ডেনিস উইলিয়ামসন

4
কি করে exec 3> "$tmpfile"? Tmpfile একটি একা একা স্ক্রিপ্ট হলে তা কি কার্যকর নয়?
আলেকজ মাগুরা

5
আপনি তৈরি এফডি থেকে কীভাবে পড়বেন?
উপস্থাপিত হয়েছে

3
"আপনি বিড়াল <3 বা অনুরূপ কিছু ব্যবহার করতে পারেন।" আসলে এটি 3 @ ড্রাগন 788 নামের একটি ফাইল থেকে পড়ে। এছাড়াও, cat <&3দেবে Bad file descriptor। আপনি যদি এটিকে ঠিক করে দেন বা অপসারণ করেন তবে আমি এটির প্রশংসা করব; ভুল তথ্য অনেক সাহায্য করে না।
ড্যানিয়েল ফারেল

65

mktempএকটি অস্থায়ী ফাইল বা ডিরেক্টরি তৈরি করতে ব্যবহার করুন :

temp_file=$(mktemp)

বা একটি নির্দেশিকা জন্য:

temp_dir=$(mktemp -d)

স্ক্রিপ্টের শেষে আপনাকে অস্থায়ী ফাইল / ডিয়ারটি মুছতে হবে:

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

mktemp /tmpডিরেক্টরিতে বা --tmpdirআর্গুমেন্টের সাথে প্রদত্ত ডাইরেক্টরিতে ফাইল তৈরি করে ।


20
আপনি trap "rm -f $temp_file" 0 2 3 15ফাইলটি তৈরি করার পরে ডান ব্যবহার করতে পারেন যাতে স্ক্রিপ্টটি প্রস্থান করার সময় বা ctrl-Cফাইলটির সাথে বন্ধ হয়ে গেলে এখনও অপসারণ করা যায়।
রবিবার

1
@ উরটেল EXITএকমাত্র হুক হলে কী হয় trap?
হউক লেগেছে

4
@ হককিজিং এরপরে স্ক্রিপ্টটি Ctrl + C দিয়ে বন্ধ করা হলে ট্র্যাপটি আর জ্বলে না। একটি বিষয় লক্ষণীয় হ'ল ট্র্যাপটি যদি আপনাকে সহায়তা করে না kill -9 $somepid। সেই বিশেষ কিল সংকেত হ'ল ইন্সটা-ডেথ এবং অন্য কিছুই ঘটছে না।
ড্রাগন 788

5
@ ড্রাগন 788 আপনি কি চেষ্টা করেছেন? তোমার উচিত. bash -c 'echo $$; trap "echo foo" 0; sleep 5'
হউক লেগেছে

আটকা পড়া EXITযথেষ্ট।
কুসালানন্দ

15

আপনি যদি mktemp আছে এমন সিস্টেমে থাকেন তবে আপনার অন্যান্য উত্তর হিসাবে এটি ব্যবহার করা উচিত।

পসিক্স টুলসেষ্টের সাথে:

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?
হউক লেগেইন

@ হককিজিং: tmpfileস্ক্রিপ্ট থেকে বের হওয়ার আগে সরিয়ে ফেলা হবে, তবে স্ক্রিপ্ট অন্যান্য সিগন্যাল পেয়ে গেলে তা নয়।
cuonglm

এখানে যা ঘটে তা তা নয় (জিএনইউ ব্যাশ, সংস্করণ 4.2.53)।
হউক লেগেছে

@ হককিজিং: আপনার অর্থ কী That's not what happens?
cuonglm

3
mktempপৃথক সিনট্যাক্স সহ এইচপি / ইউএক্সের উত্স। টড সি। মিলার 90-এর দশকের মাঝামাঝি (ফ্রিবিএসডি এবং নেটবিএসডি দ্বারা অনুলিপি করা) ওপেনবিএসডি-র জন্য একটি আলাদা একটি তৈরি করেছিলেন এবং পরবর্তীতে এটি স্ট্যান্ডএলোন ইউটিলিটি (www.mktemp.org) হিসাবেও উপলব্ধ করেছেন। mktemp২০০ the সালে জিএনইউ কোর্টিলগুলিতে একটি (বেশিরভাগ সুসংগত) ইউটিলিটি যুক্ত না হওয়া অবধি এটিই লিনাক্সে ব্যবহৃত হয়েছিল one কেবলমাত্র বলতে গেলে কেউ বলতে পারে না mktempএকটি জিএনইউ ইউটিলিটি।
স্টাফেন চেজেলাস

14

কিছু শেলের অন্তর্নির্মিত বৈশিষ্ট্য রয়েছে।

zsh

zshএর =(...)প্রক্রিয়া প্রতিকল্পন আকারে একটি অস্থায়ী ফাইল ব্যবহার করে। উদাহরণস্বরূপ =(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

$ exec 3<<< test
$ cat <&3
test
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo

(কিছু অন্যান্য শেল পাইপ ব্যবহার করে বা /dev/nullএখানে ডকটি ফাঁকা থাকলে ব্যবহার করতে পারে )।

POSIX

কোনও mktempপসিক্স ইউটিলিটি নেই। পসআইএক্স তবে একটি mkstemp(template)সি এপিআই নির্দিষ্ট করে এবং m4মানক ইউটিলিটি mkstemp()একই নামে এম 4 ফাংশন সহ সেই API টি প্রকাশ করে।

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()) করতে পারে এমন কোনও পসিক্স ইউটিলিটি নেই , সুতরাং আপনি এটি পসিক্স স্ক্রিপ্টে ( zsh( sysseekবিল্টিন) এবং ksh93( <#((...))অপারেটর) পারবেন না যদিও এটি করুন)।


1
ব্যাশের ব্যবহারের প্রক্রিয়া বিকল্প রয়েছে<()
উইনি নিক্লাউস

3
@ উইনি নিক্লাস, হ্যাঁ, তবে এটি অস্থায়ী ফাইলগুলি ব্যবহার করে না তাই এখানে অপ্রাসঙ্গিক। প্রক্রিয়া প্রতিকল্পন ksh প্রবর্তন করেন, ব্যাশ এবং zsh দ্বারা কপি, এবং zsh 3 য় ফর্ম সঙ্গে এটি বাড়ানো: =(...)
স্টাফেন চেজেলাস

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
এটি লক্ষ্য করা উচিত যে সামগ্রীটি একবারে উপলব্ধ। অর্থাৎ আমি যদি দ্বিতীয়বার বিড়াল <এবং $ এফডি_আর করি তবে কোনও আউটপুট উত্পাদিত হবে না। Unix.stackexchange.com / প্রশ্নগুলি / 166482/ … দেখুন । প্রোগ্রামটি ক্রাশ হলে ফাইলটি স্বয়ংক্রিয়ভাবে মুছে ফেলার কোনও উপায় আছে তবে এটি একাধিকবার অ্যাক্সেসযোগ্য করে তুলেছে?
স্মিহেল

0

আমার ওয়ার্কফ্লোটি সাধারণত টেম্প ফাইলগুলির সাথে হয় কারণ আমি পরীক্ষা করছি এমন কিছু বাশ স্ক্রিপ্ট। আমি teeএটি করতে চাই তাই আমি দেখতে পাচ্ছি যে এটি কাজ করছে এবং আমার প্রক্রিয়াটির পরবর্তী পুনরাবৃত্তির জন্য আউটপুট সংরক্ষণ করবে। আমি একটি ফাইল তৈরি করেছিtmp

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

যাতে আমি এটির মতো ব্যবহার করতে পারি

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

আমি এলোমেলো মানগুলির আগে ডেটটাইম ফর্ম্যাট করার কারণটি হ'ল এটি আমাকে সবেমাত্র সহজেই তৈরি করা টিএমপি ফাইলটি সন্ধান করতে দেয় এবং পরের বার এটির নাম কী রাখবেন সে সম্পর্কে আমাকে ভাবতে হবে না (এবং কেবল আমার ডাং স্ক্রিপ্ট পাওয়ার বিষয়ে মনোনিবেশ করতে হবে) কাজ করতে).

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.