Разделите строку и извлеките переменные с помощью скрипта оболочки

#shell #kubernetes #kubernetes-cronjob

Вопрос:

Вопрос

Учитывая эту однострочную строку:

 PG_USER=postgres PG_PORT=1234 PG_PASS=icontain=and*symbols  

Каков был бы правильный способ присвоить каждое значение назначенной переменной, чтобы я мог использовать его позже?


Контекст

Я анализирую контекст секрета k8s в a CronJob , чтобы периодически вызывать хранимую процедуру в нашей базе данных Postgres.

Для этого я планирую использовать:

 PG_OUTPUT_VALUE=$(PGPASSWORD=$PG_PASSWD psql -qtAX -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DATABASE -c $PG_TR_CLEANUP_QUERY)  echo $PG_OUTPUT_VALUE  

Фактическая вся схема управления, которую я сейчас пытаюсь исправить, выглядит так:

 apiVersion: batch/v1beta1 kind: CronJob metadata:  name: {{ template "fullname" $ }}-tr-cleanup-cronjob spec:  concurrencyPolicy: Forbid  schedule: "* * * * *"  jobTemplate:  spec:  template:  spec:  restartPolicy: OnFailure  volumes:  - name: postgres  secret:  secretName: {{ template "fullname" $ }}-postgres  containers:  - name: {{ template "fullname" $ }}-tr-cleanup-pod  image: postgres:12-alpine  imagePullPolicy: Always  env:  - name: PG_PROPS  valueFrom:  secretKeyRef:  name: {{ template "fullname" $ }}-postgres  key: postgres.properties  command:  - /bin/sh  - -c  - echo "props:" amp;amp; echo $PG_PROPS amp;amp; PG_USER=$(grep "^PG_USER=" | cut -d"=" -f2-) amp;amp; echo $PG_USER amp;amp; PG_TR_CLEANUP_QUERY="SELECT something FROM public.somewhere;" amp;amp; echo $PG_TR_CLEANUP_QUERY amp;amp; PG_OUTPUT_VALUE=$(PGPASSWORD=$PG_PASSWD psql -qtAX -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DATABASE -c $PG_TR_CLEANUP_QUERY) amp;amp; echo PG_OUTPUT_VALUE  volumeMounts:  - name: postgres  mountPath: /etc/secrets/postgres  

Нынешний подход

Как вы можете видеть, в настоящее время я использую:

 PG_USER=$(grep "^PG_USER=" | cut -d"=" -f2-)  

Это потому, что я изначально думал, что секрет будет выводиться в нескольких строках, но оказалось, что я ошибался. На echo $PG_USER экране отображается пустая строка.

Комментарии:

1. Ты grep ошибаешься. Каковы входные данные для команды grep ?

2. Вы правы, я должен был передать echo сообщение в качестве входных данных.

Ответ №1:

Команда bash declare здесь уместна и безопаснее, чем eval .

Предположим, что входные данные содержат что-то потенциально вредоносное

 line='PG_USER=postgres PG_PORT=1234 PG_PASS=icontain=and*symbols`ls`'  

Я предполагаю, что ни одно из значений не содержит пробелов. Давайте разделим эту строку

 read -ra assignments lt;lt;lt; "$line"  

Теперь, declare каждый из них

 for assignment in "${assignments[@]}"; do declare "$assignment"; done  

Везде, где мы изучаем входные данные, мы сохраняем двойные кавычки.

Давайте посмотрим, что у нас получилось:

 $ declare -p PG_USER PG_PORT PG_PASS declare -- PG_USER="postgres" declare -- PG_PORT="1234" declare -- PG_PASS="icontain=and*symbols`ls`"  

Ответ №2:

Вариант 1

Эту функцию можно повторно использовать для назначения каждой переменной по отдельности:

 extract() {  echo "$INPUT" | grep -o "$1=.*" | cut -d" " -f1 | cut -d"=" -f2- ; }  

И использовать его:

 PG_USER=$(extract PG_USER) PG_PORT=$(extract PG_PORT) PG_PASS=$(extract PG_PASS)  

Вариант 2

Другим потенциальным решением, связанным с безопасностью, является простое использование:

 eval "$INPUT"  

Его следует использовать только в том случае, если вы подтвердили ввод.


Контекстуальный полный ответ

И поскольку я представил контекст k8s в вопросе, вот ответ, подключенный к этому решению.

 apiVersion: batch/v1beta1 kind: CronJob metadata:  name: {{ template "fullname" $ }}-cronjob spec:  concurrencyPolicy: Forbid  schedule: "* * * * *"  jobTemplate:  spec:  template:  spec:  restartPolicy: OnFailure  volumes:  - name: postgres  secret:  secretName: {{ template "fullname" $ }}-postgres  containers:  - name: {{ template "fullname" $ }}-cronjob-pod  image: postgres:12-alpine  imagePullPolicy: Always  env:  - name: PG_PROPS  valueFrom:  secretKeyRef:  name: {{ template "fullname" $ }}-postgres  key: postgres.properties  command:  - /bin/sh  - -c  - gt;-  extract() { echo "$PG_PROPS" | grep -o "$1=.*" | cut -d" " -f1 | cut -d"=" -f2- ; } amp;amp;   export PGHOST=$(extract PG_HOST) amp;amp;  export PGPORT=$(extract PG_PORT) amp;amp;  export PGDATABASE=$(extract PG_DATABASE) amp;amp;  export PGUSER=$(extract PG_USER) amp;amp;   PG_SCHEMA=$(extract PG_SCHEMA) amp;amp;  PG_QUERY="SELECT tenant_schema FROM $PG_SCHEMA.tenant_schema_mappings;" amp;amp;   PGPASSWORD=$(extract PG_PASSWD) psql --echo-all -c "$PG_QUERY"  volumeMounts:  - name: postgres  mountPath: /etc/secrets/postgres