Разрешить переменную в переменной в оболочке

Например, могу ли я просто использовать значения cutime и cstime процесса init пространства имен для получения общего использования процессора?

Это будет включать только время waited-for (и, следовательно, завершенных) дочерних и потомков (или рип-процессов в случае init). Таким образом, вы получите время только для умерших сирот.

Если вы вычислите сумму cutime и cstime всех процессов в пространстве имен (остерегайтесь условий гонки), вы получите суммарное время всех текущих и прошлых процессов в этом пространстве имен, кроме тех, которые присоединились к пространству имен (например, с помощью nsenter -p), чье время будет учитываться их родителем в исходном пространстве имен (я обнаружил, что эти процессы имеют PPID 0 в присоединенном пространстве имен).

Также, если я смонтирую файловую систему /proc пространства имен (а не корневого пространства имен), будет ли /proc/stat показывать загрузку процессора только этого конкретного пространства имен?

Это легко проверить:

$ grep cpu /proc/stat
cpu  69003764 88576 8499514 244070762 5120799 0 407453 0 0 0
cpu0 34269946 49008 4228860 122466614 2365498 0 55409 0 0 0
cpu1 34733818 39567 4270653 121604147 2755300 0 352044 0 0 0
$ sudo unshare --mount-proc -mpf grep cpu /proc/stat
cpu  69005266 88576 8499588 244072663 5120837 0 407462 0 0 0
cpu0 34270449 49008 4228896 122467803 2365522 0 55410 0 0 0
cpu1 34734816 39567 4270692 121604860 2755315 0 352051 0 0 0

Так что, похоже, нет.

AFAICT, вы должны быть в состоянии вычислить статистику из корневого пространства имен.

Например, для пространства имен pid $pid, с zsh и perl:

perl -l -0777 -ne '
   if (/\(.*\)(?: .*?){12} (.*?) (.*?) (.*?) (.*?)/) {$s+=$1+$2+$3+$4}
   END{print $s}' /proc/*/ns/pid(e:'[[ $REPLY -ef /proc/$pid/ns/pid ]]'::h:s/ns/stat)

То есть, сложите поля с 14 по 17 из /proc/pid/stat всех процессов, которые имеют такое же пространство имен pid, как $pid.

Как сказано выше, это не включает время процессов, которые nsentered пространство имен позже и умерли (ни детей, которых они ждали (другие, похоже, были разорваны init пространства имен)).

3
03.01.2019, 10:57
3 ответа

Обратите внимание, что имена переменных в верхнем регистре, как правило, небезопасны. $ENV, например, является особенным во многих оболочках. В этих оболочках его значение должно быть путем к файлу, который будет получен перед запуском определенных типов оболочек. Оболочка bashиспользует $ENVв режиме POSIX.

Так, вbash:

declare -A account
account["develop"]=12345678
account["staging"]=9128312
account["production"]=123123

mode=$run_mode

aws events put-targets \
    --rule {{ stack_name | lower }}-hello-world \
    --targets "Id"="1","Arn"="arn:aws:lambda:us-west-2:${account[$mode]}:function:hello-wolrd"

Это устанавливает ассоциативный массив, account, который содержит данные для режимов разработки, подготовки и производства. Затем он определяет используемый нами режим и выполняет команду с правильными данными из массива account. Предполагается, что переменная run_modeявляется переменной окружения, содержащей одну из строк develop, stagingили production.

Ассоциативные массивы были введены в bash4.0.

Я использовал вашу команду awsтак, как вы ее написали (, за исключением добавления новых строк и моей accountпеременной ), хотя {{ stack_name | lower }}-hello-world, вероятно, не соответствует вашим ожиданиям (он попытается выполнить lowerкак команду ). Поскольку я не знаю aws, я не знаю, как это должно выглядеть, но, вероятно, это следует процитировать.


Устранение проблем пользователя mosvy в комментариях:В случае, когда переменные DEV_ACCOUNTи т. д. являются переменными среды, и правильный выбор должен быть сделан на основе того, что представляет собой переменная ENV:

declare -A account
account["DEV"]=$DEV_ACCOUNT
account["STAGE"]=$STAGE_ACCOUNT
account["PRD"]=$PRD_ACCOUNT

mode=$ENV

# the rest as before
4
27.01.2020, 21:15

Я повторю то, что Кусалананда сказал о неиспользовании ALLCAPS для имен переменных в сценариях оболочки. Как правило, это плохая идея и может вызвать проблемы, когда ваши имена переменных сталкиваются с переменными среды по умолчанию. И я также согласен с тем, что лучший способ сделать это — использовать ассоциативный массив, как он описывает в своем ответе.

В любом случае, если вы настаиваете на (неправильном )способе вместо массива, вам нужно будет сделать что-то вроде этого:

varname="$env"_account
aws events put-targets --rule {{ stack_name | lower }}-hello-world \
    --targets "Id"="1","Arn"="arn:aws:lambda:us-west-2:${!varname}:function:hello-world"

Синтаксис ${!var}будет расширяться до значения переменной с именем var. Например:

$ foo="foovar"
$ bar=foo
$ echo ${!bar}
foovar

А если серьезно, просто не делай этого. Это сложно, громоздко, трудно читать, сложнее поддерживать, и ассоциативный массив просто решит все эти проблемы за вас.

2
27.01.2020, 21:15

Спасибо всем, кто опубликовал ответы на мой вопрос. Я внедрил массивы bash для решения своей проблемы. Но мой друг предложил простое решение

printenv `echo $ENV`_ACCOUNT

решил мою проблему.

-1
27.01.2020, 21:15

Теги

Похожие вопросы