Вложенное цитирование в bash

#bash

#bash

Вопрос:

Я подключаюсь к удаленному серверу через SSH:

 ssh -i ~/.ssh/pk.pem user@server
 

а затем на этом сервере откройте bash в контейнере Docker:

 docker exec -it $(docker ps | grep ecs-worker-low | cut -d ' ' -f1) bash
 

Это работает нормально. (Обратите внимание, что мне нужно получить идентификатор контейнера следующим образом. Я не могу назвать контейнер.)

Я хотел бы объединить две команды, чтобы я запускал только одну команду и получал оболочку внутри контейнера. Это можно сделать с помощью чего-то вроде этого:

 ssh -i ~/.ssh/pk.pem user@server -t "bash -c 'docker exec -it $(docker ps | grep ecs-worker-low | cut -d ' ' -f1) bash'"
 

Однако это не работает из-за вложенных одинарных кавычек. Я не нашел никакого способа обойти это. Не могли бы вы мне помочь? Спасибо.

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

1. Ваша текущая команда выполняется docker ps на локальном компьютере.

Ответ №1:

Вы можете избежать использования cut с --filter и --format

 ssh -t -i ~/.ssh/pk.pem user@serve 'docker exec -it $(docker ps --filter ancestor=ecs-worker-low --format {{.ID}}) bash'
 

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

1. Это отличный момент, спасибо, Филипп. Это решает проблему с кавычками, однако, как указал @William Pursell в комментарии, команда $() фактически выполняется на моем локальном компьютере, поэтому я не могу использовать ее таким образом.

2. Это решается путем экранирования знака доллара: $ (), и это работает 🙂

3. С одинарной кавычкой перед docker exec , $() выполняется на удаленном компьютере.

Ответ №2:

Вероятно, проще всего использовать heredoc:

 ssh -i ~/.ssh/pk.pem user@server -t << EOF
docker exec -it $(docker ps | grep ecs-worker-low | cut -d ' ' -f1)
EOF
 

Убедитесь, что вы используете неинтерполирующий heredoc. Если вы опустите обратную косую черту в начальном разделителе, замена процесса будет произведена на локальном хосте.

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

1. Разве это не приводит bash к тому, что оболочка (косвенно) также наследует свой стандартный ввод из документа here?

2. @chepner Да, но это не должно быть проблемой.

Ответ №3:

Поменяйте кавычки местами:

 ssh -i ~/.ssh/pk.pem user@server -t 'bash -c "docker exec -it $(docker ps | grep ecs-worker-low | cut -d " " -f1) bash"'
 

Все двойные кавычки, насколько ssh это касается, являются буквальными символами, и подстановка команды создает новый контекст, так что первая внутренняя кавычка не закрывает первую внешнюю кавычку. Тем не менее…

… Упрощая, вам, вероятно, не нужен внешний bash ; ssh может работать docker для вас напрямую:

 ssh -i ~/.ssh/pk.pem user@server -t 'docker exec -it $(docker ps | grep ecs-worker-low | cut -d " " -f1) bash'
 

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

1. Это все еще не совсем работает из-за вложенных кавычек в аргументе cut команды. В первом случае их экранирование ( ... cut -d " " -f1 ... ) решило бы проблему, а во втором случае переключение с одинарных на двойные кавычки ( ... cut -d " " -f1 ... ) сделало бы это.

2. О, я вставил исходную команду и забыл изменить кавычки на двойные.

3. Я подозреваю, что все это спорный вопрос, если вы используете параметры --format и --filter , чтобы docker ps вывести только нужную строку, вместо того, чтобы использовать grep и cut для обработки вывода по умолчанию.

4. О, это продемонстрировал @Phillipe 🙂