একটি শেল স্ক্রিপ্ট থেকে অন্য ভেরিয়েবলগুলি অন্যটিতে পাস করবেন?


192

বলি যে এর সাথে আমার একটি শেল / বাশ স্ক্রিপ্ট test.shরয়েছে:

#!/bin/bash

TESTVARIABLE=hellohelloheloo
./test2.sh

আমার test2.shচেহারাটি এরকম:

#!/bin/bash

echo ${TESTVARIABLE}

এটা কাজ করে না. আমি সমস্ত ভেরিয়েবলগুলি প্যারামিটার হিসাবে পাস করতে চাই না যেহেতু imho এটি ওভারকিল।

অন্য কোন উপায় আছে?


একটি ধারণা হ'ল একটি ফাইলের ভেরিয়েবলগুলি সংরক্ষণ করুন এবং তারপরে অন্য স্ক্রিপ্টে লোড করুন।
রডরিগো

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

উত্তর:


264

আপনার কাছে মূলত দুটি বিকল্প রয়েছে:

  1. export TESTVARIABLE2 য় স্ক্রিপ্ট কার্যকর করার আগে ভেরিয়েবলটিকে পরিবেশের পরিবর্তনশীল ( ) করুন।
  2. দ্বিতীয় স্ক্রিপ্টটি উত্স করুন, . test2.shএবং এটি একই শেলের মধ্যে চলবে। এটি আপনাকে অ্যারেগুলির মতো আরও জটিল ভেরিয়েবলগুলি সহজেই ভাগ করতে দেয় তবে এর অর্থ হ'ল অন্যান্য স্ক্রিপ্ট উত্স শেলের মধ্যে পরিবর্তনশীলগুলি পরিবর্তন করতে পারে।

হালনাগাদ:

exportপরিবেশের ভেরিয়েবল সেট করতে ব্যবহার করতে আপনি হয় বিদ্যমান ভেরিয়েবল ব্যবহার করতে পারেন:

A=10
# ...
export A

এটি উভয় bashএবং কাজ করা উচিত shbashএটি এর মতো সংযুক্ত করার অনুমতি দেয়:

export A=10

এটি আমার মধ্যেও কাজ করে sh(যা হ'ল আপনি তা পরীক্ষা bashকরতে ব্যবহার করতে পারেন echo $SHELL)। তবে আমি বিশ্বাস করি না যে এটি সবার মধ্যে কাজ করার গ্যারান্টিযুক্ত sh, তাই এটি নিরাপদভাবে চালানো এবং এগুলি পৃথক করে দেওয়া সবচেয়ে ভাল।

আপনি যেভাবে এই রফতানি করেন তা আপনার কার্যকর করা স্ক্রিপ্টগুলিতে দৃশ্যমান হবে, উদাহরণস্বরূপ:

a.sh:

#!/bin/sh

MESSAGE="hello"
export MESSAGE
./b.sh

b.sh:

#!/bin/sh

echo "The message is: $MESSAGE"

তারপর:

$ ./a.sh
The message is: hello

এই দুটি শেল স্ক্রিপ্ট যে সত্য তাও ঘটনামূলক is পরিবেশের ভেরিয়েবলগুলি আপনার সম্পাদিত যে কোনও প্রক্রিয়াতে পাস করা যেতে পারে, উদাহরণস্বরূপ আমরা যদি অজগরটি ব্যবহার করি তবে এর পরিবর্তে এটি দেখতে দেখতে এটি হতে পারে:

a.sh:

#!/bin/sh

MESSAGE="hello"
export MESSAGE
./b.py

b.py:

#!/usr/bin/python

import os

print 'The message is:', os.environ['MESSAGE']

গুন:

পরিবর্তে আমরা এই মত উত্স পারে:

a.sh:

#!/bin/sh

MESSAGE="hello"

. ./b.sh

b.sh:

#!/bin/sh

echo "The message is: $MESSAGE"

তারপর:

$ ./a.sh
The message is: hello

এটি কমবেশি b.shসরাসরি সামগ্রীগুলি "আমদানি" করে এবং এটি একই শেলের মধ্যে কার্যকর করে । লক্ষ্য করুন যে এটির অ্যাক্সেসের জন্য আমাদের চলকটি রফতানি করতে হয়নি। এটি আপনার সমস্ত ভেরিয়েবল সুস্পষ্টভাবে ভাগ করে, পাশাপাশি অন্যান্য স্ক্রিপ্টকে শেলের মধ্যে ভেরিয়েবলগুলি যুক্ত / মুছতে / পরিবর্তন করতে দেয়। অবশ্যই, এই মডেলটিতে আপনার উভয় স্ক্রিপ্ট একই ভাষা ( shবা bash) হওয়া উচিত । একটি উদাহরণ দেওয়ার জন্য আমরা কীভাবে বার্তাগুলি পিছনে পিছনে পাস করতে পারি:

a.sh:

#!/bin/sh

MESSAGE="hello"

. ./b.sh

echo "[A] The message is: $MESSAGE"

b.sh:

#!/bin/sh

echo "[B] The message is: $MESSAGE"

MESSAGE="goodbye"

তারপর:

$ ./a.sh
[B] The message is: hello
[A] The message is: goodbye

এটি সমানভাবে ভাল কাজ করে bash। এটি আরও জটিল ডেটা ভাগ করে নেওয়া সহজ করে তোলে যা আপনি পরিবেশের পরিবর্তনশীল হিসাবে প্রকাশ করতে পারেন নি (কমপক্ষে আপনার অংশে কিছু ভারী উত্তোলন ছাড়াই) যেমন অ্যারে বা সহযোগী অ্যারেগুলি।


1
আমার যদি সাব-শেলটিতে $ 1 পাস করার প্রয়োজন হয় (কারণ 'স্ক্রিপ্ট থেকে' sudo sh -c ... 'বলা হয়)? আমি কি পরিবেশের পরিবর্তনশীল হিসাবে $ 1 স্থানান্তরিত করব, তা রফতানি করব এবং কমান্ডটিতে ভেরিয়েবলটি ব্যবহার করব?
hiরহীসিদুর

কেবল এটি যুক্ত করার জন্য যদি আপনার সুডো অ্যাক্সেসের অধিকারের প্রয়োজন হয় তবে আপনি পরিবেশের ভেরিয়েবলগুলি সংরক্ষণ করতে sudo -E ... ব্যবহার করতে পারেন।
yucer

2
@ ফ্যাটাল এররার আপনি কি দয়া করে গত আ.শ.-তে যাদুটি ব্যাখ্যা করতে পারেন, যেখানে আপনি "./b.sh" কল করেন। প্রথম বিন্দুর অর্থ কী? এটি দুর্দান্ত বিটিডব্লিউ কাজ করে!
দেিয়ান

আপনি কোনও ফাইলে ভেরিয়েবল এবং মানগুলি সেট করতে এবং
সেভাবে

@ ডিয়ান, পিরিয়ড (ডট) হ'ল "উত্স" এ নির্মিত বাশের পক্ষে
কিরিল কোস্ট

27

মারাত্মক ত্রুটি একটি সরল সম্ভাবনা দিয়েছে: উত্সটি আপনার দ্বিতীয় স্ক্রিপ্ট! যদি আপনি শঙ্কিত হন যে এই দ্বিতীয় স্ক্রিপ্টটি আপনার মূল্যবান কিছু ভেরিয়েবলের পরিবর্তন করতে পারে তবে আপনি সর্বদা এটি একটি সাব-শেইলে উত্সস্থ করতে পারেন:

( . ./test2.sh )

বন্ধনীগুলি উত্সটি একটি সাব-শেলের মধ্যে ঘটায়, যাতে প্যারেন্ট শেল পরিবর্তনগুলি test2.shসম্পাদন করতে পারে না দেখে ।


এখানে আরও একটি সম্ভাবনা রয়েছে যা অবশ্যই এখানে উল্লেখ করা উচিত: ব্যবহার set -a

থেকে POSIX setরেফারেন্স :

-a: যখন এই বিকল্পটি চালু থাকে, এক্সপোর্ট অ্যাট্রিবিউট প্রতিটি ভেরিয়েবলের জন্য নির্ধারিত হবে যেখানে একটি কার্য সম্পাদন করা হয়; আইইইই স্ট্যান্ড 1003.1-2001, বিভাগ 4.21, ভেরিয়েবল অ্যাসাইনমেন্টের বেস সংজ্ঞা ভলিউমটি দেখুন । তাহলে নিয়োগ আগে বসেছে কমান্ড একটি ইউটিলিটি নাম, রপ্তানি অ্যাট্রিবিউট বাদে ইউটিলিটি সম্পূর্ণ হওয়ার পর বর্তমান সঞ্চালনের পরিবেশে স্থির করবে না, যে বিল্ট-ইন ইউটিলিটি বিশেষ এক পূর্ববর্তী ঘটায় রপ্তানি বিল্ট পর জিদ করতে অ্যাট্রিবিউট শেষ হয়েছে। যদি অ্যাসাইনমেন্টটি কমান্ডটিতে কোনও ইউটিলিটির নামের আগে না থাকে, বা যদি অ্যাসাইনমেন্টটি গিওপ্টগুলি পরিচালনা করে বা পড়ে থাকে ইউটিলিটিস, ভেরিয়েবল আনসেট না হওয়া পর্যন্ত এক্সপোর্ট অ্যাট্রিবিউট বজায় থাকবে।

থেকে ব্যাশ ম্যানুয়াল :

-a: পরিবর্তনশীল এবং ফাংশন চিহ্নিত করুন যা পরবর্তী কমান্ডগুলির পরিবেশে রফতানি করার জন্য সংশোধিত বা তৈরি করা হয়েছে।

সুতরাং আপনার ক্ষেত্রে:

set -a
TESTVARIABLE=hellohelloheloo
# ...
# Here put all the variables that will be marked for export
# and that will be available from within test2 (and all other commands).
# If test2 modifies the variables, the modifications will never be
# seen in the present script!
set +a

./test2.sh

 # Here, even if test2 modifies TESTVARIABLE, you'll still have
 # TESTVARIABLE=hellohelloheloo

লক্ষ্য করুন যে চশমাগুলি কেবল উল্লেখ করে যে set -aচলক সহ রফতানির জন্য চিহ্নিত করা হয়েছে। এটাই:

set -a
a=b
set +a
a=c
bash -c 'echo "$a"'

প্রতিধ্বনিত হবে cএবং একটি খালি লাইনও নয় b(যা set +aরফতানির জন্য অচিহ্নিত করে না, বা এটি কেবল রফতানি পরিবেশের জন্য অ্যাসাইনমেন্টের মান "সংরক্ষণ" করে না)। এটি অবশ্যই সবচেয়ে স্বাভাবিক আচরণ।

উপসংহার: সমস্ত ভেরিয়েবল ম্যানুয়ালি রফতানির চেয়ে set -a/ ব্যবহার set +aকরা কম ক্লান্তিকর হতে পারে। এটি দ্বিতীয় স্ক্রিপ্টের উত্সাহদানের চেয়েও উন্নত, কারণ এটি কোনও শেল ভাষাতেই নয় কেবল কোনও কমান্ডের জন্য কাজ করবে।


18

আবার রফতানি ও আনসেট করা বা পুনরায় সসিংয়ের চেয়ে সহজ উপায় আছে (কমপক্ষে ব্যাশে যতক্ষণ না আপনি নিজেই পরিবেশের পরিবর্তনশীলগুলি পাস করার ক্ষেত্রে ঠিক আছেন):

আসুন

#!/bin/bash
secret="winkle my tinkle"
echo Yo, lemme tell you \"$secret\", b.sh!
Message=$secret ./b.sh

এবং বি.এস হতে

#!/bin/bash
echo I heard \"$Message\", yo

পর্যবেক্ষণ আউটপুট হয়

[রব @ আর্কি টেস্ট] $। / এ.এশ
, লে , আপনাকে "আমার টিঙ্কলটি চোখের জল মুছুন", বি.এস!
আমি শুনেছি "আমার চোখের পলক জ্বলজ্বল করুন", ইও

যাদুটির সর্বশেষ লাইনে রয়েছে a.shযেখানে Messageকেবলমাত্র আমন্ত্রণের সময়কালের জন্য ./b.sh, এর মান সেট করা secretহয়েছে a.sh। মূলত, এটি কিছুটা নামযুক্ত প্যারামিটার / আর্গুমেন্টের মতো। এর চেয়েও বেশি, এটি এমনকি ভেরিয়েবলের জন্যও কাজ $DISPLAYকরে যা কোন এক্স সার্ভারে কোন অ্যাপ্লিকেশন শুরু হয় তা নিয়ন্ত্রণ করে।

মনে রাখবেন, পরিবেশের ভেরিয়েবলের তালিকার দৈর্ঘ্য অসীম নয়। অপেক্ষাকৃত ভ্যানিলা কার্নেল সহ আমার সিস্টেমে xargs --show-limitsআমাকে আর্গুমেন্ট বাফারটির সর্বোচ্চ আকার 2094486 বাইট বলে। তাত্ত্বিকভাবে, আপনি শেল স্ক্রিপ্টগুলি ভুল ব্যবহার করছেন যদি আপনার ডেটা এর চেয়ে বড় হয় (পাইপস, কেউ?)


7

মারাত্মক ত্রুটির উত্তরে যুক্ত করা, অন্য শেল স্ক্রিপ্টে ভেরিয়েবলগুলি পাস করার আরও একটি উপায় রয়েছে।

উপরের প্রস্তাবিত সমাধানের কিছু ত্রুটি রয়েছে:

  1. using Export : এটি ভেরিয়েবলকে তাদের ক্ষেত্রের বাইরে উপস্থিত করার কারণ করবে যা একটি ভাল নকশা অনুশীলন নয়।
  2. using Source : এটির ফলে অন্য কারও শেল স্ক্রিপ্ট ফাইলের পূর্বনির্ধারিত পরিবর্তনশীলটির নাম সংঘর্ষ বা দুর্ঘটনাজনিত ওভাররাইটিং হতে পারে যা অন্য কোনও ফাইল উত্সাহী করেছে।

আমাদের ব্যবহারের জন্য সহজলভ্য আরও একটি সহজ সমাধান রয়েছে। আপনার পোস্ট করা উদাহরণ বিবেচনা করে,

test.sh

#!/bin/bash

TESTVARIABLE=hellohelloheloo
./test2.sh "$TESTVARIABLE"

test2.sh

#!/bin/bash

echo $1

আউটপুট

hellohelloheloo

এছাড়াও ""যদি আমরা মাল্টিওয়ার্ড স্ট্রিংগুলি পাস করি তবে তা নোট করা জরুরী । আরও একটি উদাহরণ গ্রহণ করা

master.sh

#!/bin/bash
echo in master.sh
var1="hello world"
sh slave1.sh $var1
sh slave2.sh "$var1"
echo back to master

slave1.sh

#!/bin/bash
echo in slave1.sh
echo value :$1

slave2.sh

#!/bin/bash
echo in slave2.sh
echo value : $1

আউটপুট

in master.sh
in slave1.sh
value :"hello
in slave2.sh
value :"hello world"

এই লিঙ্কটিতে যথাযথভাবে বর্ণিত কারণগুলির কারণে এটি ঘটে


6
ব্যবহার sourceকরা আসলে একটি ভাল জিনিস। আপনার উদ্বেগ সম্পর্কিত: একটি পূর্বনির্ধারিত ভেরিয়েবলের দুর্ঘটনাজনিত ওভাররাইটিং , আপনি সর্বদা একটি সাব-শেলতে উত্স করতে পারেন। যা সমস্যাটিকে পুরোপুরি সমাধান করে।
gniourf_gniourf 12'15

@gniourf_gniourf কীভাবে একটি সাব-শেল থেকে উত্স পাবেন?
তোসকান

@Toskan এই আমার উত্তর উল্লেখ করা হয়: ( . ./test2.sh )। প্রথম বন্ধনীগুলি বাশকে এর সামগ্রীগুলিকে একটি সাব শীলে চালিত করবে।
gniourf_gniourf

7

বাশ-এ আপনি যদি দেখানো হয়েছে এমন প্রথম বন্ধনী ব্যবহার করে কোনও সাব-শেলের মধ্যে ভেরিয়েবলটি রফতানি করেন তবে আপনি রফতানি ভেরিয়েবলগুলি ফাঁস করা এড়াতে পারেন:

#!/bin/bash

TESTVARIABLE=hellohelloheloo
(
export TESTVARIABLE    
source ./test2.sh
)

এখানে সুবিধাটি হ'ল আপনি কমান্ড লাইন থেকে স্ক্রিপ্টটি চালানোর পরে আপনি আপনার পরিবেশে একটি E টেস্টভারিয়াল ফাঁস দেখতে পাবেন না:

$ ./test.sh
hellohelloheloo
$ echo $TESTVARIABLE
                            #empty! no leak
$

আমি এটি ব্যবহার করেছি তবে এটি কার্যকর হবে বলে মনে হচ্ছে না - আমি লিখেছি: #! / বিন / বাশ ((i = 1; i <= 3; i ++)) কর (রফতানি উত্স। / Script2.sh) এর কাজটি করে বলেছেন: ./script2.sh: তেমন কোনও ফাইল বা ডিরেক্টরি নেই
গুপ্ত

শীর্ষ স্তরের পরিবেশ (কমান্ডলাইন $প্রম্পট) কখনই রফতানি দেখতে পাবে না তাই সাব - শেলটি আসলে প্রয়োজন হয় না $TESTVARIABLE। রফতানি পরবর্তী কোনও শিশু প্রক্রিয়াতে কেবল একটি ভেরিয়েবলের একটি অনুলিপি দেয় । প্যারেন্ট প্রসেস স্ক্রিপ্টে স্টোরেজে মান সংরক্ষণ করা এবং সেই স্টোরেজটি পরে পড়া ব্যতীত প্যারেন্ট প্রসেসগুলিতে চেইন ব্যাক আপ করা সম্ভব নয়। মূল স্ক্রিপ্টের দ্বিতীয় অনুলিপিটিতে পাইপিং করা সম্ভব তবে এটি একই প্রক্রিয়া হবে না । একটি দুর্দান্ত ব্যাখ্যা এখানে পাওয়া যাবে
ডকসালভাজার

2

আরেকটি বিকল্প ব্যবহার করা হয় eval। স্ট্রিংগুলিতে বিশ্বাসযোগ্য হলে এটি উপযুক্ত। প্রথম স্ক্রিপ্ট ভেরিয়েবল অ্যাসাইনমেন্টগুলি প্রতিধ্বনিত করতে পারে:

echo "VAR=myvalue"

তারপর:

eval $(./first.sh) ./second.sh

আপনি যখন দ্বিতীয় স্ক্রিপ্টের জন্য পরিবেশের ভেরিয়েবল সেট করতে চান তা এই পদ্ধতির বিশেষ আগ্রহের বিষয় নয় এবং আপনি exportভেরিয়েবলগুলিতেও চান না , সম্ভবত এগুলি সংবেদনশীল এবং আপনি এগুলি অবিরত রাখতে চান না।


1

অন্য উপায়, যা আমার পক্ষে কিছুটা সহজ, নামযুক্ত পাইপ ব্যবহার করা। নামযুক্ত পাইপগুলি বিভিন্ন প্রক্রিয়াগুলির মধ্যে সংযোগ স্থাপন এবং বার্তা প্রেরণের একটি উপায় সরবরাহ করে।

A.bash:

#!/bin/bash
msg="The Message"
echo $msg > A.pipe

B.bash:

#!/bin/bash
msg=`cat ./A.pipe`
echo "message from A : $msg"

ব্যবহার:

$ mkfifo A.pipe #You have to create it once
$ ./A.bash & ./B.bash # you have to run your scripts at the same time

বি.বাশ বার্তার জন্য অপেক্ষা করবে এবং এ্যাবশ বার্তা পাঠানোর সাথে সাথে বি.বাশ তার কাজ চালিয়ে যাবে।

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