किसी फाइल डिस्क्रिप्टर को बचाने के लिए, आप इसे दूसरे fd पर डुप्लिकेट करते हैं। संबंधित फ़ाइल के लिए एक पथ को सहेजना पर्याप्त नहीं है, आपको उद्घाटन मोड, खुलने वाले झंडे, फ़ाइल के भीतर की वर्तमान स्थिति आदि को सहेजने की आवश्यकता होगी। और निश्चित रूप से, अनाम पाइपों या सॉकेट्स के लिए, यह काम नहीं करेगा क्योंकि उनके पास कोई रास्ता नहीं है। आप जो बचाना चाहते हैं, वह है ओपन फाइल डिस्क्रिप्शन जो कि fd को संदर्भित करता है, और एक fd को डुप्लिकेट करना वास्तव में उसी ओपन फाइल डिस्क्रिप्शन में एक नया fd लौटा रहा है ।
बॉर्न-जैसे शेल के साथ फ़ाइल डिस्क्रिप्टर को दूसरे पर डुप्लिकेट करने के लिए, सिंटैक्स है:
exec 3>&1
ऊपर, fd 1 को fd 3 पर दोहराया गया है।
जो कुछ भी fd 3 बंद होने से पहले ही खुला था, लेकिन ध्यान दें कि 3 से 9 (आमतौर पर अधिक, 99 तक yash
) उस उद्देश्य के लिए आरक्षित हैं (और 0, 1, या 2 के विपरीत कोई विशेष अर्थ नहीं है), शेल अपने स्वयं के आंतरिक व्यवसाय के लिए उनका उपयोग नहीं करना जानता है। एकमात्र कारण fd 3 पहले ही खुल गया होगा क्योंकि आपने इसे स्क्रिप्ट 1 में किया था , या इसे कॉलर द्वारा लीक किया गया था।
फिर, आप स्टडआउट को कुछ और में बदल सकते हैं:
exec > /dev/null
और बाद में, stdout को पुनर्स्थापित करने के लिए:
exec >&3 3>&-
( 3>&-
फाइल डिस्क्रिप्टर को बंद करने की आवश्यकता है, जिसकी हमें अब आवश्यकता नहीं है)।
अब, इसके साथ समस्या यह है कि ksh को छोड़कर, आपके द्वारा चलायी जाने वाली प्रत्येक कमांड exec 3>&1
उस fd को इनहेरिट करेगी 3. यह एक fd लीक है। आम तौर पर एक बड़ी बात नहीं है, लेकिन यह समस्या पैदा कर सकता है।
ksh
उन fds (2 से अधिक के लिए fds) पर क्लोज़-ऑन-एग्ज़िक्यूशन फ्लैग सेट करता है , लेकिन अन्य शेल और अन्य शेल के पास उस फ़्लैग को मैन्युअल रूप से सेट करने का कोई तरीका नहीं है।
अन्य शेल के लिए चारों ओर का काम प्रत्येक और प्रत्येक कमांड के लिए fd 3 को बंद करना है, जैसे:
exec 3>&-
exec > file.log
ls 3>&-
uname 3>&-
exec >&3 3>&-
बोझिल। यहां, सबसे अच्छा तरीका यह होगा कि आप इसका उपयोग न करें exec
, लेकिन कमांड समूहों को पुनर्निर्देशित करें:
{
ls
uname
} > file.log
वहां, यह शेल है जो स्टैडआउट को बचाने और बाद में इसे पुनर्स्थापित करने के लिए ध्यान रखता है (और यह आंतरिक रूप से इसे fd पर बंद करके नकल करता है (9 से ऊपर, 99 के लिए yash
) क्लोज-ऑन-एक्ज़िक फ्लैग सेट के साथ)।
नोट 1
अब, उन 3 से 9 के fds का प्रबंधन बोझिल और समस्याग्रस्त हो सकता है यदि आप उन्हें बड़े पैमाने पर या फ़ंक्शंस में उपयोग करते हैं, खासकर यदि आपकी स्क्रिप्ट कुछ तृतीय पक्ष कोड का उपयोग करती है जो संभवतः उन fds का उपयोग कर सकती हैं।
कुछ गोले ( zsh
, bash
, ksh93
, सभी सुविधा (जोड़ा के ओलिवर महाजाल ने सुझाव दियाzsh
2005 में एक ही समय के आसपास) के बाद यह उनकी डेवलपर्स के बीच चर्चा की गई) के बजाय 10 जो इस मामले में मदद करता है ऊपर पहली मुक्त fd आवंटित करने के लिए एक विकल्प के वाक्य रचना है:
myfunction() {
local fd
exec {fd}>&1
# stdout was duplicated onto a new fd above 10, whose actual value
# is stored in the fd variable
...
# it should even be safe to re-enter the function here
...
exec >&"$fd" {fd}>&-
}