অপ্রত্যাশিত বাশ প্রস্থানে তৈরি টেম্প ফাইলগুলি সরানো


90

আমি ব্যাশ স্ক্রিপ্ট থেকে অস্থায়ী ফাইল তৈরি করছি। প্রসেসিংয়ের শেষে আমি এগুলি মুছে ফেলছি, তবে স্ক্রিপ্টটি যেহেতু বেশ দীর্ঘকাল ধরে চলছে, আমি যদি এটি চালাতে পারি বা কেবল চালনার সময় সিটিআরএল-সি, টেম্প ফাইলগুলি মুছে ফেলা হয় না।
মৃত্যুদন্ড কার্যকর হওয়ার আগে আমি কীভাবে এই ঘটনাগুলি ধরতে এবং ফাইলগুলি সাফ করতে পারি?

এছাড়াও, সেই টেম্প ফাইলগুলির নামকরণ এবং অবস্থানের জন্য কি কোনও ধরণের সেরা অনুশীলন রয়েছে?
আমি বর্তমানে ব্যবহারের মধ্যে নিশ্চিত নই:

TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...

এবং

TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...

নাহলে এর থেকেও কি আরও ভাল সমাধান হতে পারে?


এক্স-রেফ: unix.stackexchange.com/a/181938/9340
hakre

উত্তর:


99

আপনি প্রস্থান করার সময় বা পরিষ্কার-পরিচ্ছন্নতার জন্য একটি কন্ট্রোল-সিতে কার্যকর করতে " ফাঁদ " সেট করতে পারেন।

trap "{ rm -f $LOCKFILE; }" EXIT

বিকল্পভাবে, আমার পছন্দের ইউনিক্স-আইএমএসগুলির মধ্যে একটি হ'ল একটি ফাইল খুলতে হবে এবং তারপরে আপনার এখনও এটি খোলা থাকা অবস্থায় মুছুন। ফাইলটি ফাইল সিস্টেমে থাকে এবং আপনি এটি পড়তে এবং লিখতে পারেন তবে আপনার প্রোগ্রামটি প্রস্থান করার সাথে সাথে ফাইলটি চলে যায়। আপনি কীভাবে ব্যাশে এটি করবেন তা নিশ্চিত নয়।

বিটিডাব্লু: একটি যুক্তি আমি আপনার নিজের সমাধানটি ব্যবহার করার পরিবর্তে এমকেটেম্পের পক্ষে দেব: ব্যবহারকারী যদি মনে করেন যে আপনার প্রোগ্রামটি বিশাল অস্থায়ী ফাইল তৈরি করতে চলেছে, তবে তিনি সম্ভবত TMPDIRবড়ো কোনও জায়গায় / var / tmp সেট করতে চান । mktemp স্বীকৃতি জানায় যে, আপনার হাত-ঘূর্ণিত সমাধান (দ্বিতীয় বিকল্প) তা দেয় না doesn't TMPDIR=/var/tmp gvim -d foo barউদাহরণস্বরূপ আমি প্রায়শই ব্যবহার করি ।


8
ব্যাশ সঙ্গে, exec 5<>$TMPFILEবন্ধন ফাইল বর্ণনাকারী 5 read-write বৈশিষ্ট্যসহ TMPFILE ডলার, এবং আপনি ব্যবহার করতে পারেন <&5, >&5এবং /proc/$$/fd/5(লিনাক্সের) তারপরে। একমাত্র সমস্যা হল ব্যাশ লাখ টাকা seekফাংশন ...
ephemient

আপনার প্রদত্ত লিঙ্কটি যেহেতু আমার জবাব দেওয়া দরকার তার থেকে সবচেয়ে ভাল ব্যাখ্যা করার কারণে আপনি উত্তরটি গ্রহণ করেছেন। ধন্যবাদ
স্কিনপ

4
কয়েকটি নোট এতে trap: ফাঁদে যাওয়ার কোনও উপায় নেই SIGKILL(নকশার ভিত্তিতে , এটি অবিলম্বে সম্পাদন বন্ধ করে দেয়)। সুতরাং, যদি এটি হতে পারে তবে একটি ফ্যালব্যাক পরিকল্পনা করুন (যেমন tmpreaper)। দ্বিতীয়ত, ফাঁদগুলি संचयी নয় - আপনার যদি একাধিক ক্রিয়া সম্পাদন করতে থাকে তবে সেগুলি অবশ্যই trapকমান্ডের মধ্যে থাকতে হবে । একাধিক পরিষ্করণ কর্ম সঙ্গে মানিয়ে নিতে ওয়ান ওয়ে একটি ফাংশন নির্ধারণ হয় (এবং আপনি, আপনার প্রোগ্রাম আয় যেমন পুনরায় সংজ্ঞায়িত করতে প্রয়োজন হলে) এবং রেফারেন্স যে: trap cleanup_function EXIT
টবি স্পিড

4
আমাকে ব্যবহার করতে হবে trap "rm -f $LOCKFILE" EXITবা আমি ফাইল ত্রুটির একটি অপ্রত্যাশিত পরিণতি পাব।
যাক্কো

4
শেলচেক একক উদ্ধৃতি ব্যবহার করার জন্য সতর্ক করেছিল, যে ফাঁদটি প্রেরণ করা হবে তার পরিবর্তে ডাবল উদ্ধৃতি দিয়ে এক্সপ্রেশনটি 'এখন' প্রসারিত হবে।
LaFayette

110

আমি সাধারণত একটি ডিরেক্টরি তৈরি করি যেখানে আমার সমস্ত অস্থায়ী ফাইল স্থাপন করতে হবে এবং তারপরে তত্ক্ষণাত্, স্ক্রিপ্টটি প্রস্থান হওয়ার পরে এই ডিরেক্টরিটি পরিষ্কার করার জন্য একটি এক্সআইটি হ্যান্ডলার তৈরি করুন।

MYTMPDIR=$(mktemp -d)
trap "rm -rf $MYTMPDIR" EXIT

আপনি যদি আপনার সমস্ত অস্থায়ী ফাইলগুলি এর অধীনে রাখেন $MYTMPDIRতবে বেশিরভাগ পরিস্থিতিতে আপনার স্ক্রিপ্টটি প্রস্থান করলে সেগুলি সমস্ত মুছে ফেলা হবে। সিক্কিলের মাধ্যমে একটি প্রক্রিয়া হত্যা (হত্যা -9) ঠিক এখনই প্রক্রিয়াটিকে হত্যা করে, সুতরাং আপনার এক্সিট হ্যান্ডলারটি সেই ক্ষেত্রে চলবে না।


27
+1 নির্ধারিতভাবে EXIT- এ একটি ফাঁদ ব্যবহার করুন, নিরীহ TERM / INT / HUP / আপনি যা ভাবতে পারেন তা নয়। যদিও, মনে রাখবেন উদ্ধৃত আপনার পরামিতি প্রসারণও এবং আমি চাই এছাড়াও আপনাকে সুপারিশ একক উদ্ধৃতি আপনার ফাঁদ: ফাঁদ 'RM -rf "$ TMPDIR"' প্রস্থান করুন
lhunath

7
একক উদ্ধৃতি, কারণ আপনার স্ক্র্যাপটি এখনও কাজ করবে যদি পরে আপনার স্ক্রিপ্টে আপনি পরিস্থিতিগুলির কারণে TMPDIR সাফ করার এবং পরিবর্তন করার সিদ্ধান্ত নেন।
লুুনাথ

4
@ অ্যারন ডিগুল্লা কেন vs () বনাম ব্যাকটিক্স গুরুত্বপূর্ণ?
ওগ্রে গীতসংহিতা 33


4
স্বেচ্ছাসেবীর কোড কার্যকর করার ফলে ইনজেকশন প্রতিরোধ করার জন্য @ অ্যালেক্সানডারস্টলিং কোডটি সর্বদা একক-কোট হওয়া উচিত। আপনি যদি কোনও বাশ কোড STRING এ ডেটা প্রসারিত করেন তবে সেই ডেটা এখন কোনও কোডই করতে পারে যার ফলস্বরূপ নির্দোষ বাগগুলি সাদা স্থান ছড়িয়ে দেয় তবে উদ্বেগজনক বাগগুলি যেমন উদ্ভট কারণে আপনার বাড়ির ঘরের সাফ করা বা সুরক্ষা গর্ত প্রবর্তন করা যায়। নোট করুন যে ফাঁদটি বাশ কোডের একটি স্ট্রিং নেয় যা পরে হিসাবে মূল্যায়ন করা হবে। সুতরাং পরে যখন ফাঁদে আগুন জ্বলবে তখন একক উদ্ধৃতি চলে যাবে এবং সেখানে কেবল সিনট্যাক্টিকাল ডাবল উদ্ধৃতি থাকবে।
lhunath

26

স্ক্রিপ্ট বা সিটিআরএল-সি এর মতো সিগন্যালগুলি প্রস্থান করার জন্য আপনি ট্র্যাপ কমান্ডটি ব্যবহার করতে চান । দেখুন গ্রেগ এর উইকি বিস্তারিত জানার জন্য।

আপনার টেম্পাইলগুলির জন্য, ব্যবহার basename $0করা একটি ভাল ধারণা, পাশাপাশি একটি টেম্পলেট সরবরাহ করা যা পর্যাপ্ত টেম্প ফাইলগুলির জন্য জায়গা সরবরাহ করে:

tempfile() {
    tempprefix=$(basename "$0")
    mktemp /tmp/${tempprefix}.XXXXXX
}

TMP1=$(tempfile)
TMP2=$(tempfile)

trap 'rm -f $TMP1 $TMP2' EXIT

4
TERM / INT এ আটকাবেন না। এক্সিট-এ ট্র্যাপ করুন। প্রাপ্ত সিগন্যালের উপর ভিত্তি করে প্রস্থান পরিস্থিতি পূর্বাভাস দেওয়ার চেষ্টা করা নির্বোধ এবং নিশ্চিতভাবে ক্যাচল নয়।
লুুনাথ

4
গৌণ পয়েন্ট: একক ব্যাকটিকের পরিবর্তে $ () ব্যবহার করুন। এবং ডাবল কোট চারপাশে $ 0 রাখুন কারণ এতে স্পেস থাকতে পারে।
অ্যারন ডিজুল্লা

ঠিক আছে, ব্যাকটিকগুলি এই মন্তব্যে দুর্দান্ত কাজ করে তবে এটি একটি ন্যায্য বিষয়, এটি ব্যবহার করার অভ্যাসে থাকা ভাল $()। পাশাপাশি ডাবল উদ্ধৃতি যোগ করা হয়েছে।
ব্রায়ান ক্যাম্পবেল

4
আপনি আপনার পুরো সাবট্রিনটি কেবলমাত্র টিএমপি 1 = $ (টেম্পাইল-এস "এক্সএক্সএক্সএক্সএক্সএক্স") দিয়ে প্রতিস্থাপন করতে পারেন
রুসলান কাবালিন

4
@ রুসালানকাবলিন সমস্ত সিস্টেমের একটি tempfileকমান্ড থাকে না, যদিও আমি জানি যে সমস্ত যুক্তিসঙ্গত আধুনিক সিস্টেমগুলির একটি mktempকমান্ড রয়েছে।
ব্রায়ান ক্যাম্পবেল

9

শুধু মনে রাখবেন যে চুসেন উত্তর bashism, যার অর্থ সমাধান

trap "{ rm -f $LOCKFILE }" EXIT

কেবল বাশে কাজ করবে (শেল dashবা ক্লাসিক হলে এটি সিটিআরএল + সি ধরবে না sh) তবে আপনি যদি সামঞ্জস্যতা চান তবে আপনাকে যে সমস্ত সিগন্যাল ফাঁদে ফেলতে হবে তা এখনও গণনা করতে হবে।

এছাড়াও মনে রাখবেন যে স্ক্রিপ্টটি যখন "0" সিগন্যালের ফাঁদ থেকে বের হয় (আউট এক্সআইটি) সর্বদা সঞ্চালিত হয় যার ফলে trapকমান্ডের দ্বিগুণ প্রয়োগ হয়।

যদি এক্সিট সিগন্যাল থাকে তবে সমস্ত সিগন্যালকে এক লাইনে স্ট্যাক না করার কারণ।

আরও ভাল বুঝতে এটি নিম্নলিখিত স্ক্রিপ্টটি দেখুন যা কোনও পরিবর্তন ছাড়াই বিভিন্ন সিস্টেমে কাজ করবে:

#!/bin/sh

on_exit() {
  echo 'Cleaning up...(remove tmp files, etc)'
}

on_preExit() {
  echo
  echo 'Exiting...' # Runs just before actual exit,
                    # shell will execute EXIT(0) after finishing this function
                    # that we hook also in on_exit function
  exit 2
}


trap on_exit EXIT                           # EXIT = 0
trap on_preExit HUP INT QUIT TERM STOP PWR  # 1 2 3 15 30


sleep 3 # some actual code...

exit 

এই সমাধানটি আপনাকে আরও নিয়ন্ত্রণ দেবে যেহেতু আপনি চূড়ান্ত প্রস্থান ( preExitফাংশন) এর ঠিক আগে আপনার প্রকৃত সংকেত উপস্থিত হওয়ার সাথে সাথে আপনার কোডটি চালাতে পারেন এবং যদি এটির প্রয়োজন হয় তবে আপনি প্রকৃত এক্সিট সিগন্যালে (প্রস্থানের চূড়ান্ত পর্যায়ে) কিছু কোড চালাতে পারেন


4

পূর্বাভাসযোগ্য ফাইলের নামটি with এর সাথে ব্যবহারের বিকল্পটি একটি ব্যবধানযুক্ত সুরক্ষা গর্ত এবং এটি কখনই ব্যবহার করার কথা ভাবেন না। এমনকি এটি যদি আপনার একক ব্যবহারকারী পিসিতে একটি সাধারণ ব্যক্তিগত স্ক্রিপ্ট হয়। এটি একটি খুব খারাপ অভ্যাস আপনার গ্রহণ করা উচিত নয়। বাগট্রাক "অনিরাপদ টেম্প ফাইল" ঘটনায় পূর্ণ। দেখুন এখানে , এখানে এবং এখানে টেম্প ফাইলের নিরাপত্তা দৃষ্টিভঙ্গি সম্পর্কে আরও তথ্যের জন্য।

আমি প্রথমে অসুরক্ষিত টিএমপি 1 এবং টিএমপি 2 এসাইনমেন্টগুলি উদ্ধৃত করার কথা ভাবছিলাম, তবে দ্বিতীয় ভাবাতে এটি সম্ভবত একটি ভাল ধারণা হবে না


আমি যদি দিতে পারি তবে আমি দিতাম: সুরক্ষা পরামর্শের জন্য +1 এবং খারাপ ধারণা এবং রেফারেন্সের উদ্ধৃতি না দেওয়ার জন্য অন্য একটি +1
টিএমজি

2

আমি বিশ্বাস করতে পারি না যে এত লোক ধরে নিয়েছে যে কোনও ফাইলের নামের মধ্যে কোনও স্থান থাকবে না। বিশ্বটি ক্রাশ হবে যদি ever টিএমপিডিআইআরকে কখনও "অস্থায়ী ডিরেক্টরি" তে নিযুক্ত করা হয়।

zTemp=$(mktemp --tmpdir "$(basename "$0")-XXX.ps")
trap "rm -f ${zTemp@Q}" EXIT

ফাঁকা জায়গা এবং অন্যান্য বিশেষ অক্ষর যেমন একক উদ্ধৃতি এবং ফাইলের নামের সাথে ক্যারেজ রিটার্নকে শালীন প্রোগ্রামিং অভ্যাসের প্রয়োজন হিসাবে কোড হিসাবে বিবেচনা করা উচিত।


এটি লক্ষণীয় হওয়া উচিত যে ${parameter@operator}ব্যাশ 4.4 (সেপ্টেম্বর 2016 প্রকাশিত) এ বিস্তৃতি যুক্ত হয়েছিল।
রবিন এ মেইড

বাশের সমতুল্য <v4.4:trap "rm -f $(printf %q "$zTemp")" EXIT
রবিন এ।

এটি সর্বোত্তম উত্তর কারণ zTempস্ক্রিপ্টে পরে পরিবর্তিত হওয়ার মান সম্পর্কে চিন্তা করার দরকার নেই । এছাড়াও, একটি ফাংশন zTempহিসাবে ঘোষণা localকরা যেতে পারে ; এটির গ্লোবাল স্ক্রিপ্ট পরিবর্তনশীল হওয়া দরকার না।
রবিন এ Meade

1

আমি tempfileনিরাপদে উপায়ে / টিএমপি ফাইল তৈরি করে এবং এটির নামকরণ সম্পর্কে আপনাকে চিন্তা করতে হবে না:

tmp=$(tempfile -s "your_sufix")
trap "rm -f '$tmp'" exit

টেম্পাইলটি দুর্ভাগ্যক্রমে খুব সুরক্ষিত হলেও নিরাপদ, তাই এটি এড়ানো বা কমপক্ষে এটি অনুকরণ করা ভাল is
ল্যারিকসন

-4

আপনাকে এমকেটেম্প দিয়ে তৈরি সেই টিএমপি ফাইলগুলি সরাতে বিরক্ত করার দরকার নেই। সেগুলি পরে যাইহোক মুছে ফেলা হবে।

Mktemp ব্যবহার করুন যদি আপনি আরও অনন্য ফাইল তৈরি করতে পারেন তবে '$$' উপসর্গ। এটি টেম্প ফাইলগুলি তৈরি করার আরও ক্রস প্ল্যাটফর্মের মতো দেখায় তারপরে স্পষ্টভাবে এগুলিকে / tmp এ দেয় put


কিছু সময় পরে অপারেশন | ফাইল সিস্টেম নিজেই মুছে ফেলা হয়েছে
মাইকোলা গোলুবিয়েভ ২

4
যাদু? একটি ক্রোনজব? নাকি একটি রিবুটড সোলারিস মেশিন?
innaM

সম্ভবত তাদের মধ্যে একটি। যদি কোনও বাধা দ্বারা টেম্প ফাইলটি সরিয়ে না দেওয়া হয় (এটি খুব বেশি সময় হবে না) কোনও দিন টিএমপি ফাইলগুলি সরানো হবে - এজন্য তারা টেম্প বলে।
মাইকোলা গোলুয়েভ

22
আপনি এটি করতে পারবেন না, উচিত নয়, অনুমান করবেন না যে / tmp- এ দেওয়া কিছু চিরতরে সেখানে থাকবে; একই সময়ে, আপনি এটি ধরে নিবেন না যে এটি যাদুতে দূরে যাবে।
ইনানাএম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.