একটি ফাইলের পরিবেশের ভেরিয়েবলগুলি তাদের আসল মানগুলির সাথে প্রতিস্থাপন করবেন?


41

কোনও ফাইলের পরিবেশের ভেরিয়েবলগুলি বিকল্প / মূল্যায়ন করার কোন সহজ উপায় আছে? যেমনটি বলি যে আমার কাছে একটি ফাইল config.xmlরয়েছে যা এতে রয়েছে:

<property>
    <name>instanceId</name>
    <value>$INSTANCE_ID</value>
</property>
<property>
    <name>rootPath</name>
    <value>/services/$SERVICE_NAME</value>
</property>

... ইত্যাদি। আমি এনভ ভার্ভের মান সহ এনভায়রনমেন্ট ভেরিয়েবলের $INSTANCE_IDমান সহ ফাইলটিতে প্রতিস্থাপন করতে চাই । কোন পরিবেশের ভারগুলি দরকার তা আমি জানতে পারি না (অথবা কেউ যদি কনফিগার ফাইলে নতুন পরিবেশের পরিবর্তনশীল যুক্ত করে তবে আমি স্ক্রিপ্টটি আপডেট করতে চাই না)। ধন্যবাদ!INSTANCE_ID$SERVICE_NAMESERVICE_NAME


1
আপনি কখন ফাইল (বিড়াল, প্রতিধ্বনি, উত্স,…) দিয়ে কিছু করবেন যখন ভেরিয়েবলটি তার মান অনুসারে বদলে যাবে
Costas

এই এক্সএমএল ফাইলের বিষয়বস্তু কি আপনার উপর নির্ভর করে? যদি তা হয় তবে প্যারামিটারাইজড এক্সএসল্ট মানগুলি ইনজেক্ট করার জন্য আরেকটি উপায় সরবরাহ করে এবং (এনভসুবস্ট এবং এর মতো নয়) ফলস্বরূপ সুগঠিত এক্সএমএলকে গ্যারান্টি দেয়।
কোজিরো

উত্তর:


69

আপনি envsubst(অংশ gnu gettext) ব্যবহার করতে পারেন :

envsubst < infile

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


শুধুমাত্র নির্দিষ্ট পরিবেশের ভেরিয়েবলগুলি প্রতিস্থাপন করতে, এই প্রশ্নটি দেখুন।


1
... এটি আমার ডকারের ছবিতে ডিফল্টরূপে ইনস্টল না করা বাদে: '- (
রবার্ট ফ্রেজার

4
এটা ভালো. ডকারের চিত্রগুলি হালকা ওজনের এবং টেইলার তৈরি হওয়া উচিত। অবশ্যই আপনি এটি সর্বদা envsubst যোগ করতে পারে, যদিও।
কোজিরো

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

1
নোট করুন যে এটি "সমস্ত" পরিবেশের ভেরিয়েবলগুলি প্রতিস্থাপন করবে না, কেবল তাদের নাম ^[[:alpha:]_][[:alnum:]_]*$পসিক্স লোকালে মেলে ।
স্টাফেন চেজেলাস

খুব সংক্ষিপ্ত বলে মনে হয়, তবে সমস্ত প্রতিস্থাপনের মানগুলির সাথে অগত্যা সঠিক নয়। এটি XML বিশেষ অক্ষরগুলির সম্মান বলে মনে হয় না।
EFraim

16

এটি খুব সুন্দর নয় তবে এটি কাজ করে

( echo "cat <<EOF" ; cat config.xml ; echo EOF ) | sh

যদি এটি কোনও শেল স্ক্রিপ্টে থাকে তবে এটির মতো দেখতে হবে:

#! /bin/sh
cat <<EOF
<property>
    <name>instanceId</name>
    <value>$INSTANCE_ID</value>
</property>
EOF

সম্পাদনা করুন, দ্বিতীয় প্রস্তাব:

eval "echo \"$(cat config.xml)\""

সম্পাদনা করুন, প্রশ্নের সাথে কঠোরভাবে সম্পর্কিত নয়, তবে ভেরিয়েবলের ক্ষেত্রে ফাইল থেকে পড়ুন:

(. .env && eval "echo \"$(cat config.xml)\"")

এটির সাথে সমস্যাটি হ'ল যদি ফাইলটিতে একটি লাইন থাকে EOFতবে অবশিষ্ট রেখাগুলি শেল দ্বারা আদেশ হিসাবে কার্যকর হবে। আমরা বিভাজকটিকে আরও দীর্ঘতর বা আরও জটিল কিছুতে পরিবর্তন করতে পারি, তবে এখনও সংঘর্ষের একটি তাত্ত্বিক সম্ভাবনা রয়েছে। এবং কেউ আদেশগুলি কার্যকর করতে ইচ্ছাকৃতভাবে বিভাজকের সাথে একটি ফাইল তৈরি করতে পারে।
ইলকচাচ

ঠিক আছে, এটি চেষ্টা করুন: eval "প্রতিধ্বনি \" $ (বিড়াল config.xML) \ ""
hschou

3
"; ls ;"ফাইলটির অভ্যন্তরে কিছু দেওয়ার চেষ্টা করুন এবং সেই evalআদেশটি আবার করুন :) এসকিউএল ইঞ্জেকশন আক্রমণগুলির মতো এটিও একই সমস্যা। আপনি যদি না তুমি যখন কোড সহ তথ্য মিশ সত্যিই সতর্কতা অবলম্বন করা আবশ্যক (এবং কি কমান্ড শেল যে হয়) আছে সত্যিই , সত্যিই নিশ্চিত কেউ আপনার দিন জগাখিচুড়ি কিছু করতে চেষ্টা করছে।
ইলকচাচ

নং "; ls;" কোন ক্ষতি করবে না
hschou

3
@ আহসছুঃ আমার মনে হয় ইলক্কাছুর অর্থ `"; ls ;"`- মন্তব্য বিন্যাসকরণটি ব্যাকটিক্স খেয়েছে। কিন্তু আসলে যে shoule ঠিক `ls`এখানে থাকুন। মুল বক্তব্যটি হ'ল ফাইলটির বিষয়বস্তু স্বেচ্ছাচারিত কোড কার্যকর করার দিকে পরিচালিত করে এবং এটি সম্পর্কে আপনি কিছুই করতে পারবেন না।
গিলস 'অশুভ হওয়া বন্ধ করুন'

8

আপনার যদি পার্ল (তবে গেটেক্সট নয় এবং envsubst) হয়ে থাকে আপনি একটি ছোট স্ক্রিপ্টের মাধ্যমে সহজ প্রতিস্থাপনটি করতে পারেন:

$ export INSTANCE_ID=foo; export SERVICE_NAME=bar;
$ perl -pe 's/\$([_A-Z]+)/$ENV{$1}/g'  < config.xml
<property>
    <name>instanceId</name>
    <value>foo</value>
</property>
<property>
    <name>rootPath</name>
    <value>/services/bar</value>
</property>

আমি ধরে নিয়েছি পরিবর্তনশীল নামেরগুলিতে কেবল বড় হাতের অক্ষর এবং আন্ডারস্কোর থাকবে তবে প্রয়োজন অনুসারে প্রথম প্যাটার্নটি পরিবর্তন করা সহজ হওয়া উচিত। $ENV{...}পার্ল পরিবেশের উল্লেখ করে।

আপনি যদি ${...}সিনট্যাক্স সমর্থন করতে চান বা আনসেট ভেরিয়েবলগুলিতে একটি ত্রুটি নিক্ষেপ করতে চান তবে আপনার আরও কিছু কাজ প্রয়োজন। একজন ঘনিষ্ঠ সমতুল্য gettext'র envsubstহবে:

perl -pe 's/\$(\{)?([a-zA-Z_]\w*)(?(1)\})/$ENV{$2}/g'

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


পার্লটিকে ব্যবহার না করা যেহেতু এটি ডকারের ধারক হওয়ার কথা, তবে এটি সেরা সমাধানের মতো দেখাচ্ছে।
রবার্ট ফ্রেজার

2
perl -pe 's{\$(\{)?(\w+)(?(1)\})}{$ENV{$2} // $&}ge'সংজ্ঞায়িত কেবলমাত্র ভেরিয়েবলগুলি বিকল্প করতেও দেখুন ।
স্টাফেন চেজেলাস

1

আমি কি এর জন্য আমার নিজস্ব স্ক্রিপ্ট প্রস্তাব করতে পারি?

https://github.com/rydnr/set-square/blob/master/.templates/common-files/process-file.sh

#!/bin/bash /usr/local/bin/dry-wit
# Copyright 2016-today Automated Computing Machinery S.L.
# Distributed under the terms of the GNU General Public License v3

function usage() {
cat <<EOF
$SCRIPT_NAME -o|--output output input
$SCRIPT_NAME [-h|--help]
(c) 2016-today Automated Computing Machinery S.L.
    Distributed under the terms of the GNU General Public License v3

Processes a file, replacing any placeholders with the contents of the
environment variables, and stores the result in the specified output file.

Where:
    * input: the input file.
    * output: the output file.
Common flags:
    * -h | --help: Display this message.
    * -v: Increase the verbosity.
    * -vv: Increase the verbosity further.
    * -q | --quiet: Be silent.
EOF
}

# Requirements
function checkRequirements() {
  checkReq envsubst ENVSUBST_NOT_INSTALLED;
}

# Error messages
function defineErrors() {
  export INVALID_OPTION="Unrecognized option";
  export ENVSUBST_NOT_INSTALLED="envsubst is not installed";
  export NO_INPUT_FILE_SPECIFIED="The input file is mandatory";
  export NO_OUTPUT_FILE_SPECIFIED="The output file is mandatory";

  ERROR_MESSAGES=(\
    INVALID_OPTION \
    ENVSUBST_NOT_INSTALLED \
    NO_INPUT_FILE_SPECIFIED \
    NO_OUTPUT_FILE_SPECIFIED \
  );

  export ERROR_MESSAGES;
}

## Parses the input
## dry-wit hook
function parseInput() {

  local _flags=$(extractFlags $@);
  local _flagCount;
  local _currentCount;

  # Flags
  for _flag in ${_flags}; do
    _flagCount=$((_flagCount+1));
    case ${_flag} in
      -h | --help | -v | -vv | -q)
         shift;
         ;;
      -o | --output)
         shift;
         OUTPUT_FILE="${1}";
         shift;
         ;;
    esac
  done

  # Parameters
  if [[ -z ${INPUT_FILE} ]]; then
    INPUT_FILE="$1";
    shift;
  fi
}

## Checking input
## dry-wit hook
function checkInput() {

  local _flags=$(extractFlags $@);
  local _flagCount;
  local _currentCount;
  logDebug -n "Checking input";

  # Flags
  for _flag in ${_flags}; do
    _flagCount=$((_flagCount+1));
    case ${_flag} in
      -h | --help | -v | -vv | -q | --quiet)
         ;;
      -o | --output)
         ;;
      *) logDebugResult FAILURE "fail";
         exitWithErrorCode INVALID_OPTION ${_flag};
         ;;
    esac
  done

  if [[ -z ${INPUT_FILE} ]]; then
    logDebugResult FAILURE "fail";
    exitWithErrorCode NO_INPUT_FILE_SPECIFIED;
  fi

  if [[ -z ${OUTPUT_FILE} ]]; then
      logDebugResult FAILURE "fail";
      exitWithErrorCode NO_OUTPUT_FILE_SPECIFIED;
  fi
}

## Replaces any placeholders in given file.
## -> 1: The file to process.
## -> 2: The output file.
## <- 0 if the file is processed, 1 otherwise.
## <- RESULT: the path of the processed file.
function replace_placeholders() {
  local _file="${1}";
  local _output="${2}";
  local _rescode;
  local _env="$(IFS=" \t" env | awk -F'=' '{printf("%s=\"%s\" ", $1, $2);}')";
  local _envsubstDecl=$(echo -n "'"; IFS=" \t" env | cut -d'=' -f 1 | awk '{printf("${%s} ", $0);}'; echo -n "'";);

  echo "${_env} envsubst ${_envsubstDecl} < ${_file} > ${_output}" | sh;
  _rescode=$?;
  export RESULT="${_output}";
  return ${_rescode};
}

## Main logic
## dry-wit hook
function main() {
  replace_placeholders "${INPUT_FILE}" "${OUTPUT_FILE}";
}
# vim: syntax=sh ts=2 sw=2 sts=4 sr noet

0

পার্ল উত্তরের অনুরূপ, পরিবেশ পরিবর্তনশীল প্রতিস্থাপনটি পিএইচপি সিএলআই-এর প্রতিনিধি দেওয়া যেতে পারে। পিএইচপি উপর নির্ভরতা ব্যবহার প্রযুক্তির স্ট্যাকের উপর নির্ভর করে গ্রহণযোগ্য হতে পারে বা নাও পারে।

php -r 'echo preg_replace_callback("/\\$([a-z0-9_]+)/i", function ($matches) { return getenv($matches[1]); }, fread(STDIN, 8192));' < input.file > output.file

আপনি আরও যেতে পারেন এবং এটিকে পুনরায় ব্যবহারযোগ্য স্ক্রিপ্টে রাখতে পারেন, উদাহরণস্বরূপ envsubst:

#!/usr/bin/env php
<?php

echo preg_replace_callback(
    '/\$(?<name>[a-z0-9_]+)/i',
    function ($matches) {
        return getenv($matches['name']);
    },
    file_get_contents('php://stdin')
);

ব্যবহার হবে:

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