আমি কীভাবে স্ক্রিপ্টের মধ্যে একটি সম্পূর্ণ শেল স্ক্রিপ্টের আউটপুট পুনর্নির্দেশ করব?


205

বোর্ন শেল স্ক্রিপ্টের সমস্ত আউটপুট অন্য কোথাও পুনর্নির্দেশ করা সম্ভব, তবে স্ক্রিপ্টের ভিতরে শেল কমান্ডের সাহায্যে?

একটি একক কমান্ডের আউটপুট পুনঃনির্দেশ করা সহজ তবে আমি এর থেকে আরও কিছু চাই:

#!/bin/sh
if [ ! -t 0 ]; then
    # redirect all of my output to a file here
fi

# rest of script...

অর্থ: স্ক্রিপ্টটি যদি অ-ইন্টারেক্টিভভাবে চালিত হয় (উদাহরণস্বরূপ, ক্রোন), তবে সমস্ত ফাইলের আউটপুট সংরক্ষণ করুন। যদি শেল থেকে ইন্টারেক্টিভভাবে চালিত হয় তবে আউটপুটটি যথারীতি স্টাডাউটে যেতে দিন।

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

আপডেট: জোশুয়ার উত্তর স্পট-অন, তবে আমি পুরো স্ক্রিপ্টের চারপাশে স্টাডআউট এবং স্ট্ডারকে সংরক্ষণ এবং পুনরুদ্ধার করতে চেয়েছিলাম, যা এইভাবে করা হয়:

# save stdout and stderr to file descriptors 3 and 4, then redirect them to "foo"
exec 3>&1 4>&2 >foo 2>&1

# ...

# restore stdout and stderr
exec 1>&3 2>&4

2
ইন্টারেক্টিভ মোডের জন্য to TERM এর জন্য পরীক্ষা করা সবচেয়ে ভাল উপায় নয়। পরিবর্তে, stdin একটি tty (পরীক্ষা -t 0) কিনা পরীক্ষা করুন।
ক্রিস জেস্টার-ইয়ং

2
অন্য কথায়: যদি [! -t 0]; তারপরে এক্সিকিউট> সামুফিল 2> & 1; ফাই
ক্রিস জেস্টার-ইয়াং

1
সমস্ত সদাচরণের জন্য এখানে দেখুন: http://tldp.org/LDP/abs/html/io-redirection.html মূলত যিহোশূয়ের দ্বারা যা বলা হয়েছিল। এক্সিকিউটিউট> ফাইল স্টাডাউটকে একটি নির্দিষ্ট ফাইলে পুনর্নির্দেশ করে, এক্সিকিউটি <ফাইল স্ট্যান্ডিনকে ফাইল দ্বারা প্রতিস্থাপন করে, ইত্যাদি এটি যথারীতি একই তবে এক্সিকিউটিভ ব্যবহার করে (আরও বিশদে বিশদটির জন্য ম্যান এক্সিকিউট দেখুন)।
লোকি

আপনার আপডেট বিভাগে, আপনার 3 ও 4 এর মতো exec 1>&3 2>&4 3>&- 4>&-
এফডিও

উত্তর:


173

আপডেট হিসাবে প্রশ্ন সম্বোধন।

#...part of script without redirection...

{
    #...part of script with redirection...
} > file1 2>file2 # ...and others as appropriate...

#...residue of script without redirection...

ধনুর্বন্ধনী '{...}' I / O পুনঃনির্দেশের একক সরবরাহ করে। একটি কমান্ড উপস্থিত হতে পারে যেখানে ধনুর্বন্ধনী উপস্থিত হতে হবে - সরলভাবে, একটি লাইনের শুরুতে বা একটি আধা-কোলনের পরে। ( হ্যাঁ, এটিকে আরও সুনির্দিষ্ট করা যেতে পারে; যদি আপনি বাজে কথা বলতে চান তবে আমাকে জানান ))

আপনি ঠিক বলেছেন যে আপনি পুনর্নির্দেশগুলি দেখিয়েছেন আপনি মূল স্টডআউট এবং স্টডারকে সংরক্ষণ করতে পারেন, তবে উপরে বর্ণিত কোডগুলি পুনরায় নির্দেশিত কোডটি স্কোপ করলে আপনি কী করছেন তা বুঝতে পরে স্ক্রিপ্টটি বজায় রাখতে হবে এমন লোকদের পক্ষে সাধারণত সহজ।

বাশ ম্যানুয়ালটির সংশ্লিষ্ট বিভাগগুলি হ'ল গ্রুপিং কমান্ড এবং I / O পুনঃনির্দেশ । POSIX শেল স্পেসিফিকেশন সম্পর্কিত বিভাগগুলি যৌগিক কমান্ড এবং I / O পুনঃনির্দেশ । বাশের কিছু অতিরিক্ত স্বরলিপি রয়েছে তবে তা পসিক্স শেলের নির্দিষ্টকরণের মতো।


3
এটি মূল বর্ণনাকারীদের সংরক্ষণ এবং সেগুলি পরে পুনরুদ্ধার করার চেয়ে অনেক স্পষ্ট।
স্টিভ ম্যাডসেন

23
এটি আসলে কী করছে তা বুঝতে আমাকে কিছু গুগলিং করতে হয়েছিল, তাই আমি ভাগ করে নিতে চাই। কোঁকড়া ধনুর্বন্ধনী "কোডের ব্লক" হয়ে ওঠে , যা ফলস্বরূপ, একটি বেনাম ফাংশন তৈরি করে । কোড ব্লকের আউটপুট সমস্ত কিছুই পুনঃনির্দেশিত করা যায় ( সেই লিঙ্ক থেকে উদাহরণ 3-2 দেখুন )। এছাড়াও নোট করুন যে কোঁকড়া ধনুর্বন্ধকগুলি একটি সাবশেল আরম্ভ করে না , তবে একইভাবে আই / ও পুনর্নির্দেশগুলি প্রথম বন্ধনী ব্যবহার করে সাবসেলের মাধ্যমে করা যেতে পারে।
ক্রিস

3
আমি এই সমাধানটি অন্যদের চেয়ে ভাল পছন্দ করি। এমনকি কেবলমাত্র I / O পুনঃনির্দেশের প্রাথমিক বোধগম্য কোনও ব্যক্তি কী ঘটছে তা বুঝতে পারে। এছাড়াও, এটি আরও ভার্জোজ। এবং, পাইথোনার হিসাবে, আমি ভার্বোস পছন্দ করি।
জন রেড

আরও ভাল করা >>। কিছু মানুষের অভ্যাস থাকে >। সংযোজন সর্বদা সুরক্ষিত এবং ওভার *** ইনগের চেয়ে বেশি প্রস্তাবিত। কেউ একটি অ্যাপ্লিকেশন লিখেছিলেন যা একই গন্তব্যে কিছু ডেটা রপ্তানি করতে স্ট্যান্ডার্ড কপি কমান্ড ব্যবহার করে।
neverMind9

সেই অ্যাপ্লিকেশনটি সিসি.বি.এম.এম.71 (.প্রো) (3 সি ব্যাটারি মনিটর উইজেট, পূর্বে "ব্যাটারি মনিটর উইজেট") সর্বদা ব্যাটারি ইতিহাসকে /sdcard/bmw_history.txt এ রপ্তানি করে। যদি ইতিমধ্যে উপস্থিত থাকে তবে অনুমান করুন কী, ওভারওয়ারিট! এটি আমাকে অবিচ্ছিন্নভাবে কিছু ব্যাটারির ইতিহাস হারাতে বাধ্য করে। আমি 30 দিনের থেকে খুব উচ্চ সংখ্যায় সীমাটি নির্ধারণ করেছিলাম, যা এটিকে অবৈধ করে এটিকে 30 এ ফিরিয়ে দিয়েছে the বিদ্যমান ব্যাকআপটি আমদানির আগে আমি বর্তমান ব্যাটারি ইতিহাস রপ্তানি করতে চেয়েছিলাম। তারপরে তা ঘটেছিল।
neverMind9

175

সাধারণত আমরা এগুলির একটি স্ক্রিপ্টের শীর্ষে বা কাছাকাছি রাখব। যে ক্রিপ্টগুলি তাদের কমান্ড লাইনকে বিশ্লেষণ করে তা বিশ্লেষণের পরে পুনর্নির্দেশটি করবে।

Stdout একটি ফাইল পাঠান

exec > file

stderr সঙ্গে

exec > file                                                                      
exec 2>&1

stdout এবং stderr উভয় ফাইল যোগ করুন

exec >> file
exec 2>&1

যেমন জোনাথন লেফলার তার মন্তব্যে উল্লেখ করেছেন :

execদুটি পৃথক কাজ আছে। প্রথমটি হ'ল বর্তমানে চালিত শেল (স্ক্রিপ্ট) কে একটি নতুন প্রোগ্রামের সাথে প্রতিস্থাপন করা। অন্যটি বর্তমান শেলের আই / ও পুনর্নির্দেশগুলি পরিবর্তন করছে। কোন যুক্তি না থাকার দ্বারা এটি আলাদা করা যায় exec


7
আমি বলি যে এরপরে 2> ও 1 যুক্ত করুন, সুতরাং স্ট্যাডার খুব বেশি ধরা পড়ে। :-)
ক্রিস জেস্টার-ইয়াং

7
এগুলো কোথায় রাখো? স্ক্রিপ্টের শীর্ষে?
কোলান

4
এই সমাধানের সাথে একজনকে পুনর্নির্দেশ স্ক্রিপ্টের প্রস্থানটি পুনরায় সেট করতে হবে। জোনাথন লেফলারের পরবর্তী উত্তর এই অর্থে আরও "ব্যর্থ প্রমাণ"।
চুইম

6
@ জনরেড: execদুটি পৃথক কাজ রয়েছে। একটি হ'ল বর্তমান প্রক্রিয়াটিকে একই কমান্ডের সাথে অন্য কমান্ডের সাথে প্রতিস্থাপন করা - আপনি অন্য কমান্ডটিকে যুক্তি হিসাবে উল্লেখ করেন exec(এবং আপনি যেমন করছিলেন তেমন I / O পুনর্নির্দেশগুলিও টুইট করতে পারেন)। অন্য কাজটি প্রতিস্থাপন না করে বর্তমান শেল স্ক্রিপ্টে আই / ও পুনর্নির্দেশগুলি পরিবর্তন করছে। আর্গুমেন্ট হিসাবে একটি কমান্ড না রেখে এই স্বরলিপিটি পৃথক করা হয় exec। এই উত্তরের স্বরলিপিটি "I / O কেবল" বৈকল্পিকের - এটি কেবল পুনঃনির্দেশটি পরিবর্তন করে এবং যে স্ক্রিপ্টটি চলছে তা প্রতিস্থাপন করে না। ( setকমান্ডটি একইভাবে বহুমুখী -)
জোনাথন লেফলার

18
exec > >(tee -a "logs/logdata.log") 2>&1স্ক্রিনে লগগুলি মুদ্রণের পাশাপাশি একটি ফাইলে লেখেন
shriyog

32

আপনি পুরো স্ক্রিপ্টকে এই জাতীয়ভাবে একটি ফাংশন করতে পারেন:

main_function() {
  do_things_here
}

তারপরে স্ক্রিপ্টের শেষে এটি রয়েছে:

if [ -z $TERM ]; then
  # if not run via terminal, log everything into a log file
  main_function 2>&1 >> /var/log/my_uber_script.log
else
  # run via terminal, only output to screen
  main_function
fi

বিকল্পভাবে, আপনি প্রতিটি রান লগফাইলে সমস্ত কিছু লগইন করতে পারেন এবং স্ট্যান্ডআউটে কেবল আউটপুট এটিকে আউটপুট করতে পারেন:

# log everything, but also output to stdout
main_function 2>&1 | tee -a /var/log/my_uber_script.log

আপনি কি মূল_ফংশানটি >> /var/log/my_uber_script.log 2> এবং 1
ফিলিপ আলভারেজ

আমি এই জাতীয় পাইপে main_function ব্যবহার করতে পছন্দ করি। তবে এক্ষেত্রে আপনার স্ক্রিপ্টটি মূল রিটার্ন মান দেয় না। বাশ ক্ষেত্রে আপনার 'প্রস্থান $ IP পাইপস্ট্যাটাস [0]}' ব্যবহার করে প্রস্থান করা উচিত।
rudimeier

7

মূল স্ট্ডআউট এবং স্ট্ডার সংরক্ষণের জন্য আপনি ব্যবহার করতে পারেন:

exec [fd number]<&1 
exec [fd number]<&2

উদাহরণস্বরূপ, নিম্নলিখিত কোডটি "ওয়াল্লা 1" এবং "ওয়ালা 2" লগ ফাইলে ( a.txt) প্রিন্ট করবে, স্টাডআউটে "ওয়াল্লা 3", স্ট্রেডারে "ওয়াল্লা 4" প্রিন্ট করবে ।

#!/bin/bash

exec 5<&1
exec 6<&2

exec 1> ~/a.txt 2>&1

echo "walla1"
echo "walla2" >&2
echo "walla3" >&5
echo "walla4" >&6

1
সাধারণত, এটি ব্যবহার করার জন্য ভাল হবে exec 5>&1এবং exec 6>&2, আউটপুট জন্য ইনপুট ফেরৎ স্বরলিপি আউটপুট ফেরৎ স্বরলিপি বদলে ব্যবহার করে। আপনি এটির সাথে দূরে চলে যান কারণ স্ক্রিপ্টটি যখন কোনও টার্মিনাল থেকে চালিত হয়, তখন স্ট্যান্ডার্ড ইনপুটটিও লিখনযোগ্য হয় এবং স্ট্যান্ডার্ড আউটপুট এবং মান ত্রুটি উভয়ই historicalতিহাসিক কীর্তির গুণ (বা এটি 'ভাইস'?) দ্বারা পাঠযোগ্য হয়: টার্মিনালটির জন্য খোলা হয় পড়া এবং লেখা এবং একই ওপেন ফাইলের বিবরণ তিনটি মানক I / O ফাইল বর্ণনাকারীর জন্য ব্যবহৃত হয়।
জোনাথন লেফলার

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