जवाबों:
एक अस्थायी फ़ाइल के मामले में, प्रश्न में आपका उदाहरण इसे बनाएगा, फिर निर्देशिका से इसे अनलिंक कर देगा (इसे "गायब" कर देगा), और जब स्क्रिप्ट दर्जकर्ता (संभवत: समाप्ति पर) बंद हो जाती है, तो फ़ाइल द्वारा लिया गया स्थान सिस्टम द्वारा पुनः प्राप्त किया जा सकेगा। C जैसी भाषाओं में अस्थायी फ़ाइलों से निपटने का यह एक सामान्य तरीका है।
यह है, जहां तक मुझे पता है, एक निर्देशिका को उसी तरह से खोलना संभव नहीं है, कम से कम किसी भी तरह से ऐसा नहीं है जो निर्देशिका को सार्थक बना सके।
स्क्रिप्ट की समाप्ति पर अस्थायी फ़ाइलों और निर्देशिकाओं को हटाने का एक सामान्य तरीका एक सफाई EXIT
जाल स्थापित करना है । नीचे दिए गए कोड उदाहरण पूरी तरह से दर्जकर्ता को हथकंडा करने से बचाते हैं।
tmpdir=$(mktemp -d)
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"; rm -rf "$tmpdir"' EXIT
# The rest of the script goes here.
या आप एक सफाई समारोह कह सकते हैं:
cleanup () {
rm -f "$tmpfile"
rm -rf "$tmpdir"
}
tmpdir=$(mktemp -d)
tmpfile=$(mktemp)
trap cleanup EXIT
# The rest of the script goes here.
EXIT
जाल प्राप्त होने पर निष्पादित नहीं किया जाएगा KILL
संकेत (जो ट्रैप नहीं किया जा सकता है), जिसका अर्थ है कि वहाँ हो जाएगा कोई सफाई तो प्रदर्शन किया। हालांकि यह निष्पादित करेंगे जब एक की वजह से समाप्त INT
या TERM
संकेत (अगर साथ चल रहा bash
या ksh
, अन्य गोले में आप के बाद इन संकेतों को जोड़ सकते हैं EXIT
में trap
कमांड लाइन), या जब सामान्य रूप से कारण स्क्रिप्ट के अंत में आ रहा है या एक को क्रियान्वित करने के लिए बाहर निकलने exit
कहते हैं।
.
और ..
प्रविष्टियाँ भी नहीं हैं। (लिनक्स पर परीक्षण किया गया, मुझे नहीं पता कि क्या यह प्लेटफ़ॉर्म पर संगत है।)
exec another-command
स्पष्ट रूप से कॉल करता है तो EXIT जाल को निष्पादित नहीं किया जाता है ।
एक शेल-फंक्शन लिखें जिसे आपकी स्क्रिप्ट खत्म होने पर निष्पादित किया जाएगा। नीचे दिए गए उदाहरण में मैं इसे 'सफाई' कहता हूं और बाहर निकलने के स्तर पर निष्पादित होने के लिए एक जाल सेट करता हूं, जैसे: 0 1 2 3 3 6
trap cleanup 0 1 2 3 6
cleanup()
{
[ -d $TMP ] && rm -rf $TMP
}
अधिक जानकारी के लिए इस पोस्ट को देखें ।
cleanup
एक स्वच्छ निकास (0) से पहले और SIGHUP (1), SIGINT (2), SIGQUIT (3) और SIGABRT (6) प्राप्त करने पर चलेगा। यह तब नहीं चलेगा cleanup
जब स्क्रिप्ट SIGTERM, SIGSEGV, SIGKILL, SIGPIPE आदि के कारण बाहर निकल जाए, यह स्पष्ट रूप से कमी है।
आप इसमें chdir कर सकते हैं और फिर इसे हटा सकते हैं, बशर्ते कि आप इसके अंदर के रास्तों का उपयोग करने की कोशिश न करें:
#! /bin/sh
dir=`mktemp -d`
cd "$dir"
exec 4>file 3<file
rm -fr "$dir"
echo yes >&4 # OK
cat <&3 # OK
cat file # FAIL
echo yes > file # FAIL
मैंने जाँच नहीं की है, लेकिन यह शायद एक ही समस्या है जब सी में ओपनैट (2) का उपयोग एक निर्देशिका के साथ किया जाता है जो अब फ़ाइल सिस्टम में मौजूद नहीं है।
यदि आप रूट पर हैं और लिनक्स पर हैं, तो आप एक अलग नामस्थान और उसके mount -t tmpfs tmpfs /dir
अंदर खेल सकते हैं ।
यदि आपकी स्क्रिप्ट एक अशुद्ध निकास (जैसे SIGKILL के साथ) में मजबूर हो तो विहित उत्तर (EXIT पर एक जाल सेट) काम नहीं करते हैं; जो संवेदनशील डेटा को चारों ओर लटका हुआ छोड़ सकता है।
अपडेट करें:
यहाँ एक छोटी सी उपयोगिता है जो नेमस्पेस दृष्टिकोण को लागू करती है। इसके साथ संकलित किया जाना चाहिए
cc -Wall -Os -s chtmp.c -o chtmp
और दी गई CAP_SYS_ADMIN
फ़ाइल क्षमताओं (रूट के रूप में) के साथ
setcap CAP_SYS_ADMIN+ep chtmp
जब (एक सामान्य) उपयोगकर्ता के रूप में चलाते हैं
./chtmp command args ...
यह अपने फाइल सिस्टम नेमस्पेस को अनशेयर करेगा, इसमें एक tmpfs फाइल सिस्टम माउंट करेगा /proc/sysvipc
, इस पर chdir और command
दिए गए तर्कों के साथ चल सकता है। क्षमताओं को विरासत में नहींcommand
मिलेगा ।CAP_SYS_ADMIN
वह फाइलसिस्टम किसी अन्य प्रक्रिया से सुलभ नहीं होगा जहां से शुरू नहीं हुआ है command
, और यह जादुई रूप से गायब हो जाएगा (सभी फाइलों के साथ जो इसके अंदर बनाई गई थीं) जब command
और उसके बच्चों की मृत्यु हो जाती है, तो कोई फर्क नहीं पड़ता कि ऐसा कैसे होता है। ध्यान दें कि यह केवल माउंट नेमस्पेस को अनचेक कर रहा है - command
एक ही उपयोगकर्ता द्वारा संचालित और अन्य प्रक्रियाओं के बीच कोई कठिन बाधाएं नहीं हैं ; वे अभी भी या तो के माध्यम से अपने नाम स्थान के अंदर चुपके सकता है ptrace(2)
, /proc/PID/cwd
या अन्य तरीकों से।
"बेकार" /proc/sysvipc
का अपहरण निश्चित रूप से मूर्खतापूर्ण है, लेकिन विकल्प /tmp
खाली निर्देशिकाओं के साथ स्पैम के लिए होता है जिन्हें हटाया जाना चाहिए या कांटे और इंतजार के साथ इस छोटे से कार्यक्रम को जटिल करना होगा। वैकल्पिक रूप से, dir
उदाहरण के लिए बदला जा सकता है। /mnt/chtmp
और इसे स्थापना पर मूल द्वारा बनाया गया है; इसे उपयोगकर्ता-कॉन्फ़िगर करने योग्य न बनाएं और इसे उपयोगकर्ता के स्वामित्व वाले पथ पर सेट न करें क्योंकि यह आपको सहानुभूति जाल और अन्य बालों वाले सामान पर खर्च करने के लिए उजागर कर सकता है।
chtmp.c
#define _GNU_SOURCE
#include <err.h>
#include <sched.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mount.h>
int main(int argc, char **argv){
char *dir = "/proc/sysvipc"; /* LOL */
if(argc < 2 || !argv[1]) errx(1, "usage: %s prog args ...", *argv);
argv++;
if(unshare(CLONE_NEWNS)) err(1, "unshare(CLONE_NEWNS)");
/* "modern" systemd remounts all mount points MS_SHARED
see the NOTES in mount_namespaces(7); YUCK */
if(mount("none", "/", 0, MS_REC|MS_PRIVATE, 0))
err(1, "mount(/, MS_REC|MS_PRIVATE)");
if(mount("tmpfs", dir, "tmpfs", 0, 0)) err(1, "mount(tmpfs, %s)", dir);
if(chdir(dir)) err(1, "chdir %s", dir);
execvp(*argv, argv);
err(1, "execvp %s", *argv);
}
rm $PWD
काम में, शेल उस डायर में अभी भी है। लेकिन कोई भी नई फाइल इस "फ़ोल्डर" में नहीं डाली जा सकती है। केवल आप ऐसा कर सकते हैं / फ़ाइल और 3, और 4 के साथ पढ़ा / लिखा जा सकता है। तो यह अभी भी "अस्थायी फ़ाइल" है, न कि "अस्थायी फ़ोल्डर"।
क्या आपको एक विशिष्ट शेल की आवश्यकता है?
यदि zsh एक विकल्प है, तो कृपया पढ़ें zshexpn(1)
:
यदि <(...) के बजाय = (...) का उपयोग किया जाता है, तो एक तर्क के रूप में पारित फाइल सूची प्रक्रिया के आउटपुट वाले एक अस्थायी फ़ाइल का नाम होगा। इनपुट फ़ाइल पर
lseek
(देखेंlseek(2)
) की अपेक्षा करने वाले प्रोग्राम के लिए इसका उपयोग <फॉर्म के बजाय किया जा सकता है ।[...]
एक अन्य समस्या किसी भी समय है कि एक अस्थायी फ़ाइल की आवश्यकता है एक प्रतिस्थापन के साथ एक नौकरी खोल द्वारा अस्वीकृत किया जाता है इस मामले में जहां भी शामिल है, उठता है
&!
या&|
एक आदेश एक प्रतिस्थापन युक्त के अंत में दिखाई देता है। उस मामले में अस्थायी फ़ाइल को साफ नहीं किया जाएगा क्योंकि शेल में अब नौकरी की कोई स्मृति नहीं है। एक वर्कअराउंड का उपयोग करने के लिए एक उपधारा, उदाहरण के लिए,(mycmd =(myoutput)) &!
के रूप में forked उपधारा समाप्त होने के लिए प्रतीक्षा करेगा, तो अस्थायी फ़ाइल को हटा दें।
एक उचित लंबाई के लिए एक प्रक्रिया प्रतिस्थापन अंत सुनिश्चित करने के लिए एक सामान्य समाधान यह है कि इसे एक गुमनाम शेल फ़ंक्शन के पैरामीटर के रूप में पास किया जाए (शेल कोड का एक टुकड़ा जो फ़ंक्शन गुंजाइश के साथ तुरंत चलाया जाता है)। उदाहरण के लिए, यह कोड:
() { print File $1: cat $1 } =(print This be the verse)
निम्नलिखित के समान कुछ आउटपुट
File /tmp/zsh6nU0kS: This be the verse
उदाहरण के लिए मैं एक फाइल को डिक्रिप्ट करने के लिए राइफल (रेंजर फाइल मैनेजर का हिस्सा) में इसका उपयोग करता हूं और फिर अस्थायी फाइल पर राइफल चलाता हूं, जो उपप्रकार समाप्त होने पर हटा दी जाती है। (सेट करना न भूलें $TERMCMD
)
# ~/.config/ranger/rifle.conf
...
!ext exe, mime octet-stream$, has gpg, flag t = () { rifle -f F "$1" } =(gpg -dq "$1")