আমি কি বাশগুলিতে "রফতানি" করতে পারি?


80
source some_file

some_file:

doit ()
{
  echo doit $1
}
export TEST=true

যদি আমি কিছু_ফায়ার উত্সটি " doit " ফাংশন এবং ভেরিয়েবল TEST কমান্ড লাইনে উপলব্ধ। তবে এই স্ক্রিপ্টটি চালাচ্ছেন:

script.sh:

#/bin/sh
echo $TEST
doit test2

TEST এর মান ফিরিয়ে দেবে, তবে অজানা ফাংশন "doit" সম্পর্কে ত্রুটি উত্পন্ন করবে।

আমি কি ফাংশনটি "রফতানি" করতে পারি, অথবা সেখানে ফাংশনটি ব্যবহার করতে আমার স্ক্রিপ্ট.শনে কিছু_ফাইল উত্স করতে হবে?


2
পরিবর্তন: নীচের উত্তর (যেমন প্রশ্ন ইঙ্গিত enzotib সঠিক, অভিমানী আপনি ব্যাশ ব্যবহার করতে পারেন, হয়) সংক্ষেপিত #!/bin/shকরার #!/bin/bashএবং পরে doit() {...} মাত্রexport -f doit
মাইকেল

কেবলমাত্র রেকর্ডের জন্য: আপনি যখন #!/bin/shখুব বেশি ব্যবহার করেন তখন এই সমাধানটি সাধারণত কাজ করবে তবে এটি ব্যবহার করা ভাল অনুশীলন #!/bin/bashযাতে ডিফল্ট শেলটি বাশ না করাতে আপনি সমস্যাগুলি এড়ান।
নাগেল

উত্তর:


119

বাশে আপনি ফাংশন সংজ্ঞাটি সাব-শেলের সাথে রফতানি করতে পারেন

export -f function_name

উদাহরণস্বরূপ আপনি এই সহজ উদাহরণটি ব্যবহার করে দেখতে পারেন:

./script1:

    #!/bin/bash

    myfun() {
        echo "Hello!"
    }

    export -f myfun
    ./script2

./script2:

    #!/bin/bash

    myfun

তারপরে আপনি কল ./script1করলে আউটপুট দেখতে পাবেন হ্যালো!


16

ব্যবহার export -fকরে একটি ফাংশন "রফতানি" ফাংশন বডি সহ পরিবেশের পরিবর্তনশীল তৈরি করে । এই উদাহরণ বিবেচনা করুন:

$ fn(){ echo \'\"\ \ \$; }
$ export -f fn
$ sh -c printenv\ fn
() {  echo \'\"\ \ \$
}

এর অর্থ হ'ল কেবল শেল (কেবল বাশ?) ফাংশনটি গ্রহণ করতে সক্ষম হবে। আপনি ফাংশনটি নিজেই সেট করতে পারেন যেমন বাশ কেবল () {ফাংশন হিসাবে শুরু হওয়া এনভায়ারদের বিবেচনা করে:

$ fn2='() { echo Hi;}' sh -c fn2
Hi
$ fn3='() {' sh -c :
sh: fn3: line 1: syntax error: unexpected end of file
sh: error importing function definition for `fn3'

আপনার যদি এসএসএইচ এর মাধ্যমে এই পরিবর্তনশীলটি "রফতানি" করতে হয় তবে আপনার স্ট্রিং হিসাবে ফাংশনটি সত্যই প্রয়োজন। এই মুদ্রণ বিকল্প (সঙ্গে কাজ করা যেতে পারে -pফাংশন (জন্য) -fএর) declareবিল্ট-ইন:

$ declare -pf fn
fn () 
{ 
    echo \'\"\ \ \$
}

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

#!/bin/bash
remote_main() {
   local dest="$HOME/destination"

   tar xzv -C "$dest"
   chgrp -R www-data "$dest"
   # Ensure that newly written files have the 'www-data' group too
   find "$dest" -type d -exec chmod g+s {} \;
}
tar cz files/ | ssh user@host "$(declare -pf remote_main); remote_main"

fn2='() { echo Hi;}' sh -c fn2আমার জন্য কাজ করে না। shবাশ v5.0.7 হওয়ার সাথে খিলান লিনাক্সে পেয়েছি sh: fn2: command not foundshV0.2.3 ড্যাশ হওয়ার সাথে সাথে উবুন্টুতে আমি পেয়েছি sh: 1: fn2: not found। আপনি কোন shশেল ব্যবহার করেছেন?
সোসোইই

আমি মনে করি আপনার উত্তরটি ভুল। f(){ echo a;}; export -f f; echo "$f"; sh -c 'printenv f; echo "$f"'আমার জন্য কিছুই মুদ্রণ করে না, সুতরাং স্পষ্টভাবে fস্ট্রিং স্ট্রিং হিসাবে রফতানি হয় না। আমি উপরে উল্লিখিত উভয় সংমিশ্রণ দিয়ে পরীক্ষা করেছি।
সোসোইই

এমনকি যদি ফাংশনটি একটি স্ট্রিং হিসাবে রফতানি করা হয় তবে কেন shসেই স্ট্রিংটিকে একটি ফাংশন হিসাবে চালানো উচিত ? আপনার উদাহরণে fn2='() { echo Hi;}' sh -c fn2কমান্ড fn2দেওয়া sh আক্ষরিক স্ট্রিং "fn2"shএর PATH তে এই জাতীয় কমান্ড সন্ধান করা উচিত তবে কোনও ভেরিয়েবল আছে কিনা তা দেখে নেওয়া উচিত নয়$fn2 , সেই পরিবর্তনশীলটি প্রসারিত করা উচিত এবং এর মানটি একটি ফাংশন হিসাবে কার্যকর করা উচিত - এটি আমার কাছে একটি বড় সুরক্ষার সমস্যার মতো মনে হচ্ছে। সম্পাদনা: আমার মনে হয় এটাই! আপনার প্রদর্শিত আচরণটি কি সুরক্ষা বাগটি শেলশক / বাশদুর নামে পরিচিত ছিল ?
সোসোইই

বাশ 5.0.7 (আর্চ লিনাক্স) এর সাহায্যে এটি উপস্থিত হয় যে একটি উপসর্গ চাপানো হয়েছে। এটি সম্ভবত শেলশকের প্রতিক্রিয়াতে করা হয়েছিল। উদাহরণ: fn(){ echo foo; }; export -f fn; env | grep fooফলাফলগুলিBASH_FUNC_fn%%=() { echo foo
লেকেনস্টেইন

7

@ লেকেনস্টেইনের উত্তরের ভিত্তিতে বিল্ডিং ...

আপনি যদি declare -pfএটি ব্যবহার করেন তবে বর্তমান শেলের সমস্ত পূর্বনির্ধারিত ফাংশনগুলি STDOUT এ আউটপুট করে।

সেই মুহুর্তে আপনি যেখানেই চান সেখানে স্টডআউট পুনর্নির্দেশ করতে পারেন এবং কার্যকরভাবে পূর্বনির্ধারিত ফাংশনগুলি যেখানেই আপনি চাইবেন স্টাফ করুন।

নিম্নলিখিত উত্তরগুলি এগুলিকে ভেরিয়েবলে পরিণত করবে। তারপরে আমরা সেই পরিবর্তনশীল এবং আরও নতুন ফাংশনটির আমন্ত্রণটি প্রতিধ্বনিত করি যা আমরা নতুন ব্যবহারকারী হিসাবে প্রবর্তিত নতুন শেলটিতে চালাতে চাই। আমরা ব্যবহার করে এই কাজ sudoসঙ্গে -u(ওরফে। user) সুইচ কেবল ব্যাশ চলমান (যা ইনপুট চালানোর জন্য যেমন পাইপ stdout- এ পাবেন)।

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

আপনি যদি বিভিন্ন শেলের মধ্যে বা ব্যাশের বিভিন্ন সংস্করণ থাকতে পারে এমন সিস্টেমের মধ্যে চলে যান তবে ওয়াইএমএমভি।

#!/bin/bash
foo() {
  echo "hello from `whoami`"
}

FUNCTIONS=`declare -pf`; echo "$FUNCTIONS ; foo" | sudo -u otheruser bash
# $./test.sh
# hello from otheruser

5

আপনি যেভাবে বর্ণনা করছেন সেভাবে নয়, আপনি ফাংশনগুলি রফতানি করতে পারবেন না। শেলটি কেবলমাত্র ~/.bashrcএকটি ইন্টারেক্টিভ শেলের শুরুতে ফাইলটি লোড করবে ( ব্যাশ ম্যানপেজে "অনুরোধ" অনুসন্ধান করুন )।

আপনি যা করতে পারেন তা হল "লাইব্রেরি" তৈরি করা যা আপনি প্রোগ্রাম শুরু করার সময় লোড হয়:

source "$HOME/lib/somefile"

এবং আপনার অ-ইন্টারেক্টিভ ফাংশন এবং সেটিংসগুলি সেখানে রাখুন।


সুতরাং আমাকে "লগইন" পরামিতি (পার্সিং /। /। প্রোফাইলে) বা সেই ফাইলটি উত্স দিয়ে সাবসেল শুরু করতে হবে।
নিলস

অ-ইন্টারেক্টিভ শেলগুলিতে আরও কিছুটা ঘনিষ্ঠভাবে তাকালে আপনি ইতিমধ্যে আপনার BASH_ENVকাছে পরিবেশের পরিবর্তনশীল সেট some_fileকরতে পারেন এবং এটি ডাকা হবে। এটি খুঁজে পাওয়া যথেষ্ট সহজ হবে:echo echo foobar > /tmp/foobar; BASH_ENV=/tmp/foobar $SHELL -c :
আর্জেজ করুন

2

eval "$(declare -F | sed -e 's/-f /-fx /')"সমস্ত ফাংশন রফতানি করবে ।

স্ক্রিপ্টের ফাংশন এবং ভেরিয়েবলগুলি ব্যবহার করার সময় আমাকে ডিবাগ করতে এবং স্ক্রিপ্ট প্রসঙ্গে কাজ করতে সক্ষম করতে স্ক্রিপ্টে একটি ইন্টারেক্টিভ শেল শুরু করার আগে আমি এটি অনেক কিছু করি do

উদাহরণ:

eval "$(declare -F | sed -e 's/-f /-fx /')"
export SOME IMPORTANT VARIABLES AND PASSWORDS
bash -i

1

ফাংশনগুলি সাব-প্রসেসগুলিতে রফতানি হয় না। এই কারণেই .kshrc বা .bashrc নামে ফাইল রয়েছে: ফাংশনগুলি সংজ্ঞায়িত করতে যেগুলি শাইওল্ড সাব-শেলগুলিতে উপলব্ধ।

যদি কোনও স্ক্রিপ্ট চলমান থাকে তবে। * Shr স্ক্রিপ্টগুলি সাধারণত উত্সযুক্ত হয় না। আপনাকে এমন কোড করতে হবে যা স্পষ্টভাবে, পছন্দ করতে হবে . ~/.kshrc


সুতরাং স্ক্রিপ্টগুলি মূল হিসাবে চালিত হওয়ায় case মূল / .bashrc আমার ক্ষেত্রে একটি বিকল্প হতে পারে। এই ইঙ্গিতটির জন্য ধন্যবাদ
নিলস

। * স্ক্র্যাচ ফাইলগুলি ব্যবহার করা হলে নিশ্চিত হন যে তারা মিথস্ক্রিয় আচরণকে বাধ্য করবেন না (বোকা ওরফে মত rm=rm -i)
কেটিএফ

0

ঠিক আছে, আমি লিনাক্সে নতুন, তবে আপনি এটি ব্যবহার করে দেখতে পারেন। কিছু ফাইলে, আসুন একে কল করুন, 'টিএমপি / জেনারেল' আপনি নিজের ফাংশনটি তৈরি করেন:

func1(){
   echo "func from general"
}

আপনার শেল স্ক্রিপ্ট এ যোগ করুন:

. /tmp/general

এবং চালান:

func1

স্ক্রীনের পাবেন: func from general


0
declare -x -f NAME

অধিক তথ্য

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