কোনও ফাইল বর্ণনাকারী বৈধ কিনা তা পরীক্ষা করা হচ্ছে


12

আমি ব্যাশ স্ক্রিপ্ট আউটপুট অতিরিক্ত তথ্য তৈরি করতে চাই যখন তারা খোলা থাকে তখন 3 এর চেয়ে বেশি বা সমান সংখ্যক বর্ণনাকারী (এফডি) ফাইল করতে পারে। কোনও এফডি খোলা আছে কিনা তা পরীক্ষা করতে, আমি নিম্নলিখিত কৌশলটি তৈরি করেছি:

if (printf '' 1>&3) 2>&-; then
  # File descriptor 3 is open
else
  # File descriptor 3 is not open
fi

এটি আমার প্রয়োজনের জন্য যথেষ্ট, তবে আমি যদি এফডি বৈধ হয় তবে পরীক্ষার আরও বেশি বুদ্ধিমান উপায় আছে কিনা তা সম্পর্কে আমি আগ্রহী। আমি বিশেষ করে কিনা সেখানে একটি ম্যাপিং বিদ্যমান আগ্রহী fcntl(1)(ক শেল কমান্ড প্রাপ্ত syscall, যা এফডি পতাকার আহরণ সম্ভব হবে O_WRONLYএবং O_RDWRপরীক্ষা করা হবে কিনা তা এফডি লিখনযোগ্য, এবং O_RDONLYএবং O_RDWRপরীক্ষা করা হবে কিনা তা এফডি পাঠযোগ্য)।

উত্তর:


12

ইন ksh(উভয় AT & T ও pdksh রূপগুলো) অথবা zsh, আপনি কি করতে পারেন:

if print -nu3; then
  echo fd 3 is writeable
fi

তারা এফডি তে কিছু লিখবে না, তবুও এফডিটি লেখার যোগ্য (ব্যবহার করে fcntl(3, F_GETFL)) রয়েছে কিনা তা পরীক্ষা করে অন্যথায় ত্রুটিটি রিপোর্ট করে:

$ ksh -c 'print -nu3' 3< /dev/null
ksh: print: -u: 3: fd not open for writing

(যা আপনি পুনর্নির্দেশ করতে পারেন /dev/null)।

এর সাথে bash, আমি মনে করি আপনার একমাত্র বিকল্পটি dup()আপনার পদ্ধতির মতো সফল হয়েছে কিনা তা যাচাই করা হবে, যদিও এটি গ্যারান্টি দেয় না যে fd লেখার যোগ্য (বা এটি করার জন্য একটি বাহ্যিক ইউটিলিটি ( zsh/ perl...) কল করে fcntl())।

মনে রাখবেন যে bash(বেশিরভাগ শাঁসের মতো), আপনি যদি এর (...)পরিবর্তে ব্যবহার করেন তবে {...;}এটি একটি অতিরিক্ত প্রক্রিয়া তৈরি করবে। তুমি ব্যবহার করতে পার:

if { true >&3; } 2<> /dev/null

কাঁটাচামচ এড়ানোর জন্য (বোর্ন শেল ব্যতীত যেখানে কম্পাউন্ড কমান্ড পুনঃনির্দেশ করা সর্বদা সাবসেলের কারণ হয়ে থাকে)। এটি একটি বিশেষ বিল্টিন হিসাবে :পরিবর্তে ব্যবহার করবেন না , সুতরাং যখন পশিক্স কমপ্লায়েন্স মোডে বাশ থাকে শেলটি প্রস্থান করতে পারে।true

তবে আপনি এটি সংক্ষিপ্ত করতে পারেন:

if { >&3; } 2<> /dev/null

@ মাইক্রিজ, রি: আপনার এডিট, এর সাথে <>কী? শেলটি তার স্টাডার থেকে পড়তে যাচ্ছে না, আপনি কেন এটি পড়তে + লেখাতে খুলতে চান? অভ্যন্তরীণ যা ঘটেছিল তার সাথে আপনি কী বোঝাতে চাইছেন ? ?
স্টাফেন চেজেলাস

7

পসিক্স অ্যাপ্লিকেশন ব্যবহারের বিবরণীতে আপনি নিম্নলিখিতটি পাবেন:command

উপলক্ষে বিশেষ বিল্ট-ইনগুলির বিশেষ বৈশিষ্ট্যগুলি দমন করার কিছু সুবিধা রয়েছে। উদাহরণ স্বরূপ:

command exec > unwritable-file

কোনও ইন্টারঅ্যাক্টিভ স্ক্রিপ্টটি বাতিল করতে দেয় না, যাতে স্ক্রিপ্ট দ্বারা আউটপুট স্থিতি পরীক্ষা করা যায়।

এজন্য আপনি কেবল করতে পারেন:

if    command >&3
then  echo 3 is open >&3
else  ! echo 3 is not open
fi    2<>/dev/null

অথবা ...

{ command >&3
  printf %s\\n%.0d  string "0$(($??8:0))" >&"$(($??1:3))"
} 2<>/dev/null

কোনটি লিখতে হবে স্ট্রিং একটি দ্বারা অনুসরণ \nপারেন stdout- এ বা 3 এবং এখনও করার ewline একটি নন-জিরো প্রস্থান অবস্থা পাস যখন 3 খোলা কারণ গণিত সম্পন্ন নয় $?অকট্যাল রূপান্তর করতে ব্যর্থ আপ বাতাস 08 থেকে % দশমিক এ সব কিছুই কিন্তু কাটছাঁট করে অকট্যাল 00

অথবা ...

command exec >&3 || handle_it

তবে আপনি যদি ব্যবহার করেন তবে আপনি ksh93কেবল এটি করতে পারেন:

fds

ওপেন ফাইল বর্ণনাকারীদের তালিকার জন্য। যোগ -lদেখতে যেখানে তারা যান।


3

ওপেন ফাইল বর্ণনাকারী পাওয়া যাবে /proc/<pid>/fd। উদাহরণস্বরূপ, বর্তমান শেলটির খোলার ফাইল বর্ণনাকারী তালিকাবদ্ধ করতে ls -l /proc/$$/fdযা আপনাকে কিছু দিতে হবে:

total 0
lrwx------ 1 testuser testuser 64 jun  1 09:11 0 -> /dev/pts/3
lrwx------ 1 testuser testuser 64 jun  1 09:11 1 -> /dev/pts/3
lrwx------ 1 testuser testuser 64 jun  1 09:11 2 -> /dev/pts/3
lrwx------ 1 testuser testuser 64 jun  1 09:39 255 -> /dev/pts/3

আপনি যখন কোনও ফাইল খুলতে ব্যবহার করেন:

touch /tmp/myfile
exec 7</tmp/myfile

এটি একটি নতুন দ্বারা তালিকাভুক্ত করা উচিত ls -l /proc/$$/fd:

lr-x------ 1 testuser testuser 64 jun  1 09:11 7 -> /tmp/myfile

আপনি যদি আবার ফাইল বর্ণনাকারী ব্যবহার করে exec 7>&-এটি বন্ধ করেন তবে এটি /proc/$$/fdআর তালিকাভুক্ত নয়।


2
এই সমস্ত লিনাক্সের জন্য যথেষ্ট নির্দিষ্ট। FWIW।
lcd047

1
এটি লিনাক্সের পাশাপাশি সোলারিসে পরীক্ষা করা হয়েছে (10 এবং 11)। পার্থক্যটি হ'ল লিনাক্সের সাথে সংযোগটি প্রদর্শন করার pfiles <pid>সময় কোন ফাইল বর্ণনাকারী কোন ফাইলের সাথে সংযুক্ত রয়েছে তা দেখতে আপনার প্রয়োজন ls -l
ল্যামবার্ট

আমি এর কমপ্যাক্টনেসটি [ -e /proc/$$/fd/3 ]পছন্দ করি তবে আমি ফিক্সফের উপর নির্ভর করা পছন্দ করি না, কারণ এটি ফ্রিবিএসডি এবং সম্ভবত অন্যান্য ইউএনএসকেও অবমূল্যায়িত করা হয়েছে।
উইটিকো

1
কোন ফাইলের বর্ণনাকারী খোলা আছে তা ব্যবহার করার বিকল্পটি দেখতে pfiles <pid>বা আমার কাছে নিয়ে আসে lsof -p <pid>
ল্যামবার্ট

1
/procওপেনবিএসডি-তে মোটেও নেই। ফ্রিবিএসডি এবং নেটবিএসডি-তে এটি mountস্পষ্টভাবে বিড করতে হবে , এবং /proc/<PID>একটি উপ-ডিরেক্টরি নেই fd
lcd047

3

আপনার কৌশলটি দেখতে সুন্দর লাগছে; তবে একটি অহঙ্কারী পদ্ধতিতে আমি অবাক হয়েছি আপনি কেন ব্যবহার করেন নি:

if ( exec 1>&3 ) 2>&-

এটি প্রকৃতপক্ষে একটি পরিষ্কার উপায়।
উইটিকো

5
এটি একটি সাবশেল তৈরি করে যদিও বেশিরভাগ শাঁস মানেই কোনও প্রক্রিয়া তৈরি করা। এটি গ্যারান্টি দেয় না যে এফডি লেখার যোগ্য। { true >&3; } 2> /dev/nullকাঁটাচামচ এড়াতে আপনি ব্যবহার করতে পারেন । অথবা { command exec >&3; } 2> /dev/nullআপনি যদি স্টডআউটকে এটি পুনর্নির্দেশ করতে চান।
স্টাফেন চেজেলাস

@Stephane; @ উইটিকো যে সাবশেল ট্রিক্সটি আবিষ্কার করেছিলেন তা হ'ল রিডাইরেকশনটি প্রাপ্ত করতে পুনঃনির্দেশ ব্যবহার করার সময় বর্তমান পরিবেশের ফাইল বর্ণনাকারীদের প্রভাবিত করবে না। - আপনি যে "লিখনযোগ্য এফডি" উল্লেখ করেছেন তা কী আপনি বিশদভাবে বলতে পারেন?
জানিস

2
{ true >&3; } 2> /dev/nullবর্তমান পরিবেশকেও প্রভাব ফেলবে না এবং কাঁটাচামচ করবে না (বোর্ন শেল ব্যতীত)। আমি বোঝাতে চাইছি যে (exec 1>&3) 2>&-কেবল পঠনযোগ্য মোডে একটি এফডি ওপেনের জন্য সত্য হবে।
স্টাফেন চেজেলাস

1
execএকটি বিশেষ অন্তর্নির্মিত হওয়ায় শেলটি প্রস্থান করে না তবে (ব্যাশের জন্য, কেবলমাত্র পসিক্স কমপ্লায়েন্স মোডে থাকলে)। command execযে বাধা দেয়। trueএকটি বিশেষ অন্তর্নির্মিত না। নোট করুন execএবং command execবর্তমান পরিবেশকে প্রভাবিত করুন (সে কারণেই যদি আমি বলেছিলাম যে আপনি যদি স্টাডাউটকে এটিতে পুনঃনির্দেশ করতে চান )।
স্টাফেন চেজেলাস

-1

আপনি যদি বার বার পুনরায় ব্যবহার করার জন্য কোনও কম কাঁটা সমাধানে আগ্রহী হন তবে আমি এই ফাংশনটি সুপারিশ করব:

চেকফডি () {
    এক্সিকিউটিভ 2> / দেব / নাল
    যদি এক্সিকিউট> & 3; তারপর
        এক্সিকিউটিভ 1> / দেব / টিটিআই
        প্রতিধ্বনি "fd3 ঠিক আছে"
    আর
        প্রতিধ্বনি "এফডি 3 কো"
    ফাই
    এক্সিকিউটিভ 2> / দেব / টিটি
}

এবং এটি এখানে যা তৈরি করে তা এখানে zsh:

$ চেকফডি            
fd3 KO
$ চেকএফডি 3> / দেব / নাল
fd3 ঠিক আছে
$

exec >&33 টি খোলা না থাকলে বেশিরভাগ শেলগুলিতে শেলটি মেরে ফেলবে।
মাইকসার্ভ

কমপক্ষে এটি কাজ করছে zshএবং bash। আপনি কি শেলটি সরবরাহ করতে পারেন যার উপর ব্যর্থতার execকারণে একটি হয়েছিল exit?
ডান

হ্যাঁ। ইন bashনা set -o posixআবার চেষ্টা করুন। ইন zsh... আমি মনে করি এটি এনভ ভার্জকে ন্যূনতম POSIX_BUILTINSমান হিসাবে সেট করার বিষয় - তবে আমি অফেন্ডকে ভুলে যাই। যাই হোক, zshএকটি শেল যা POSIX সম্মতি প্রচেষ্টা, এবং তাই এটি নিশ্চিতভাবেই অ-মানক নয়। সেই শেল পরিহার সামঞ্জস্য দুজনেই কি জন্য কিছু বিশ্বাস সুবিধার্থে।
মাইকেসার্ভ

এটি প্লেইন বোর্ন শেলটিতেও কাজ করছে।
ডান

ব্যাশে, set -o posixচেষ্টা করে সফল হয়।
ডান

-1

এটি অত্যন্ত সহজ বলে মনে হচ্ছে (মন্তব্যগুলি দেখুন):

[ -r /proc/$$/fd/$FD ] && echo "File descriptor $FD is readable"
[ -w /proc/$$/fd/$FD ] && echo "File descriptor $FD is writable"

অতিরিক্ত হিসাবে ... [-r ফাইল] পরীক্ষাটি নির্দেশ করে না যে কোনও তথ্য আসলে পড়ার জন্য অপেক্ষা করছে (/ dev / নাল এই পরীক্ষাটি পাস করেছে (মন্তব্যগুলি দেখুন))।

[ -r /proc/$$/fd/4 ] \
  && [ read -t 0.0001 -N 0 <&4 ] \
  && echo "Data is waiting to be read from file descriptor 4"

টাইমআউট আর্গুমেন্টের জন্য কিছু ছোট সংখ্যা (পড়ুন-টি) প্রয়োজন বা ডেটা যার জন্য কিছু গণনা প্রয়োজন মিস করা যেতে পারে। পঠনযোগ্য পরীক্ষা ([-r ফাইল]) প্রয়োজন বা ফাইলটি পাঠযোগ্য না হলে রিড কমান্ড বোমা দেবে। এটি আসলে কোনও ডেটা পড়বে না কারণ বাইট গণনা শূন্য (পঠন -N 0)।


আপনি যদি একটি লিনাক্স সিস্টেম ধরে নিতে চলেছেন তবে আপনার ঠিক তেমন একটি নজর থাকতে পারে /proc/<pid>/fdinfo/<fd>, যা নীচে থাকা সমস্ত উন্মুক্ত ফাইলগুলির তালিকা তালিকাভুক্ত করে flags:- এখানে দেখুন । কেন আপনার ২ য় অংশ (সুস্পষ্ট ভুল সংশোধন করার পরেও): read -t .1 -N0 <&4এফডি 4 এ ডেটা পড়তে হবে কিনা তা বলবে না: কেবল চেষ্টা করে দেখুন 4</dev/null
মশবী

এবং অবশ্যই, [ -r /proc/$$/fd/$FD ]ফাইল বর্ণনাকারী $FDপাঠযোগ্য কিনা তা আপনাকে জানায় না , তবে ফাইলটি যদি খোলা থাকে তবে এটি পড়ার জন্য অন্য একটি ফাইল বর্ণনাকারী সহ আবার খুলতে পারে :exec 7>/tmp/foo; [ -r /proc/$$/fd/7 ] && echo fd 7 can be read from && cat <&7
ম্যাসভি

-1

প্রশ্নটি বেশ পুরানো - তবে যাইহোক - কেন কেবল বিল্টিন ব্যবহার করবেন না?

for i in {0..5} ; do if [ -t $i ]; then echo "$i is a valid FD"; else echo "$i is INVALID FD"; fi; done

আউটপুট:

0 is a valid FD
1 is a valid FD
2 is a valid FD
3 is INVALID FD
4 is INVALID FD
5 is INVALID FD

সুতরাং, প্রশ্নের উত্তর দিতে - পরামর্শ দেবে:

if [ -t 3 ]; then
  # File descriptor 3 is open
else
  # File descriptor 3 is not open
fi

-tকোনও ফাইল বর্ণনাকারী বৈধ কিনা তা পরীক্ষা করে না, তবে এটি টিটিটির সাথে সংযুক্ত থাকলে। echo yup |আপনার স্ক্রিপ্টে একটি প্রস্তুত করুন, এবং এটি বলবে 0 is INVALID FD, বাস্তবে এটি খুব বৈধ এফডি, একটি পাইপ।
মোশি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.