При запуске команды в perl6, команды, работающие в оболочке, выдают ошибку при запуске внутри perl6 - PullRequest
0 голосов
/ 24 января 2019

Я пытаюсь запустить серию команд оболочки с Perl6 для переменной $cmd, которая выглядит как

databricks jobs run-now --job-id 35 --notebook-params '{"directory": "s3://bucket", "output": "s3://bucket/extension", "sampleID_to_canonical_id_map": "s3://somefile.csv"}'

  1. Разделение команды на все послеnotebook-params

my $ cmd0 = 'Задания для работы с базами данных - сейчас -job-id 35 --notebook-params';my $ args = "'{\" directory \ ": \" $ in-dir \ ", \" output \ ": \" $ out-dir \ ", \" sampleID_to_canonical_id_map \ ": \" $ map \ "}«";my $ run = run $ cmd0, $ args,: err,: out;

Сбой.Никакого ответа не дали ни Databricks, ни оболочка.Stdout и stderr пусты.

Разделение всей команды по пробелам

my @cmd = $ cmd.split (/ \ s + /);my $ run = run $ cmd,: err,: out

Ошибка: получены неожиданные дополнительные аргументы ("s3: // bucket", "output": "s3:// bucket / extension "," sampleID_to_canonical_id_map ":" s3: //somefile.csv "} '

Передача команды в виде строки my $ cmd = "$ cmd0 \" $ in-dir \ ", \" output \ ": \" $ out-dir \ ", \" sampleID_to_canonical_id_map \ ": \" $ map\ "} '";

снова, stdout и stderr пусты.Код выхода 1.

это то, что run может принимать только массивы, а не строки (мне интересно, почему)

Если я скопирую и вставлю команду, которая была переданаPerl6 run, он работает, если он дан из оболочки.Это не работает, когда передается через perl6.Это нехорошо, потому что я должен выполнить эту команду сотни раз.

Возможно, оболочка Perl6 https://docs.perl6.org/routine/shell будет лучше?Я не использовал это, потому что руководство предполагает, что run безопаснее.Я хочу записать как stdout, так и stderr в Proc class

EDIT: я запустил это с shell, но столкнулся с другими проблемами, не связанными с тем, что я первоначально опубликовал.Я не уверен, если это квалифицируется как ответ тогда.Я просто решил использовать backticks с perl5.Да, обратные пометки устарели, но они выполняют свою работу.

Ответы [ 2 ]

0 голосов
/ 24 января 2019

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

Чтобы запустить команды оболочки, вызовите процедуру shell. Он передает предоставленный вами позиционный аргумент, приведенный к одной строке, в оболочку системы, на которой вы запускаете программу P6.

Для запуска команд без использования оболочки вызовите процедуру run. Первый позиционный аргумент приводится к строке и передается операционной системе в качестве имени файла программы, которую вы хотите запустить. Остальные аргументы объединяются вместе с пробелом между каждым аргументом, образуя единственную строку, которая передается в качестве командной строки выполняемой программе.

my $cmd0 = 'databricks jobs run-now --job-id 35 --notebook-params ';

Это неправильно как для shell, так и для run:

  • shell принимает только один аргумент, а $cmd0 является неполным.

  • Первый аргумент для run - это строка, интерпретируемая ОС как имя файла программы, которую нужно запустить, а $cmd0 не является именем файла.

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

Другие два ваших эксперимента также недействительны, как вы обнаружили.

это что-то о том, как run может принимать только массивы, а не строки (мне интересно, почему)

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

Может принимать два аргумента. Первым будет имя программы, а вторая командная строка, переданная программе.

Может принимать три или более аргументов. Первым будет имя программы, остальные будут объединены, чтобы сформировать командную строку, переданную программе. (Существуют случаи, когда это удобнее в кодировании, чем в форме с двумя аргументами.)

run также может принимать один массив. Первым элементом будет имя программы, а остальная командная строка передается ей. (Есть случаи, когда это удобнее.)

Я просто решил использовать backticks с perl5. Да, обратные пометки устарели, но они сделали свою работу.

Обратные помехи подвергаются внедрению кода , атакам и ошибкам интерполяции оболочки. Но да, если они работают, они работают.

P6 имеет прямые эквиваленты большинства функций P5. Это включает в себя кавычки. У P6 есть два варианта:

  • Более безопасная альтернатива бэкстикам P6 - qx. Конструкция с кавычками qx вызывает оболочку, но не интерполирует переменные P6, поэтому имеет такой же уровень опасности, что и использование shell с одной строкой в ​​кавычках.

  • Вариант qqx является прямым эквивалентом обратных кавычек P5 или использует shell со строкой в ​​двойных кавычках, поэтому он страдает от тех же угроз безопасности.

0 голосов
/ 24 января 2019

Две ошибки:

  • упрощенный split разбивает последний единственный параметр на несколько аргументов
  • вы передаете $cmd для запуска, а не @cmd
use strict;

my @cmd = ('/tmp/dummy.sh', '--param1', 'param2 with spaces');
my $run = run @cmd, :err, :out;

print(@cmd ~ "\n");
print("EXIT_CODE:\t" ~ $run.exitcode  ~ "\n");
print("STDOUT:\t"    ~ $run.out.slurp ~ "\n");
print("STDERR:\t"    ~ $run.err.slurp ~ "\n");

вывод:

$ cat /tmp/dummy.sh
#!/bin/bash
echo "prog: '$0'"
echo "arg1: '$1'"
echo "arg2: '$2'"
exit 0

$ perl6 dummy.pl
/tmp/dummy.sh --param1 param2 with spaces
EXIT_CODE:      0
STDOUT: prog: '/tmp/dummy.sh'
arg1: '--param1'
arg2: 'param2 with spaces'

STDERR:

Если вы можете избежать генерации $cmd как одной строки, я бы сгенерировал ее непосредственно в @cmd.В противном случае вам придется реализовать сложную операцию разбиения, которая обрабатывает кавычки.

...