Как мне сохранить значение, возвращаемое либо run, либо shell? - PullRequest
0 голосов
/ 31 декабря 2018

Допустим, у меня есть этот сценарий:

# prog.p6
my $info = run "uname";

Когда я запускаю prog.p6, я получаю:

$ perl6 prog.p6
Linux

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

Уже есть аналогичный вопрос , но он не дает конкретного ответа.

Ответы [ 3 ]

0 голосов
/ 31 декабря 2018

Решение, описанное в этом ответе, является кратким.

Это иногда перевешивает его недостатки:

  • Не сохраняет код результата.Если вам это нужно, используйте вместо этого решение ugexe.

  • Не сохраняет вывод в stderr.Если вам это нужно, используйте вместо этого решение ugexe.

  • Потенциальная уязвимость.Это объясняется ниже.Вместо этого рассмотрите решение ugexe.


Документирование описанных ниже функций начинается с наречие цитаты :exec.

Самый безопасный небезопасный вариант: q

Самый безопасный вариант использует один q:

say qx[ echo 42 ] # 42

Если есть ошибка, то конструкция возвращает пустую строку, и любое сообщение об ошибке появится в stderr.

Этот самый безопасный вариант аналогичен одиночной строке в кавычках, такой как 'foo', передаваемой в оболочку.Строки в одинарных кавычках не интерполируют , поэтому нет никакой уязвимости для атаки внедрения кода .

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

Наименее безопасный небезопасный вариант: qq

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

say qqx[ echo 42 ]

Этот вариант с двойным q аналогичен строке с двойными кавычками ("foo").Эта форма строкового цитирования выполняет интерполяцию , что означает, что она подвергается атаке внедрения кода , если вы включите переменную в строку, переданную оболочке.

0 голосов
/ 31 декабря 2018

По умолчанию run просто передает STDOUT и STDERR родительскому процессу STDOUT и STDERR.

Вы должны сказать ему сделать что-то еще.

Самое простое - просто дать ему :out, чтобы сказать, чтобы оно оставалось STDOUT.(Сокращенно от :out(True))

my $proc = run 'uname', :out;
my $result = $proc.out.slurp(:close);
my $proc = run 'uname', :out;
for $proc.out.lines(:close) {
  .say;
}

Вы также можете эффективно сказать ему просто отправить STDOUT на /dev/null с помощью :!out.(Сокращенно от :out(False))


Есть еще несколько вещей, которые вы можете сделать с :out

{
  my $file will leave {.close} = open :w, 'test.out';
  run 'uname', :out($file); # write directly to a file
}

print slurp 'test.out'; # Linux
my $proc = run 'uname', :out;

react {
  whenever $proc.out.Supply {
    .print

    LAST {
      $proc.out.close;
      done; # in case there are other whenevers
    }
  }
}

Если вы собираетесь сделать это в последний раз, этовероятно лучше использовать Proc :: Async.

0 голосов
/ 31 декабря 2018

Вам необходимо включить канал stdout, который по умолчанию имеет значение $*OUT, установив :out.Итак:

my $proc = run("uname", :out);
my $stdout = $proc.out;
say $stdout.slurp;
$stdout.close;

, который можно сократить до:

my $proc = run("uname", :out);
say $proc.out.slurp(:close);

Если вы хотите захватить вывод на stderr отдельно от stdout, вы можете сделать:

my $proc = run("uname", :out, :err);
say "[stdout] " ~ $proc.out.slurp(:close);
say "[stderr] " ~ $proc.err.slurp(:close);

или если вы хотите захватить stdout и stderr в один канал, то:

my $proc = run("uname", :merge);
say "[stdout and stderr] " ~ $proc.out.slurp(:close);

Наконец, если вы не хотите захватывать вывод и не хотите выводить его на терминал:

my $proc = run("uname", :!out, :!err);
exit( $proc.exitcode );
...