список не будет транслироваться в команду qacct [duplicate]

Два println оператора обрабатываются двумя разными потоками. Результат снова зависит от того, в какой среде вы запускаете код. Например, я выполнил следующий код в IntelliJ и в командной строке по 5 раз.

  public class Test {public static void main (String [] args) {for (int i = 0; i & lt; 10; i ++) {System.out.print ("OUT")  ;  System.err.print («ERR»);  }}}  

Это приводит к следующему выводу: Commandline

  OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR  OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR  OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR  

IntelliJ:

  ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR  ERR ERR ERR ERR ERR OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT ERR ERR ERR ERR ERR  ERR ERR ERR ERR ERR  

Я полагаю, что разные среды обрабатывают буфер иначе. Один из способов увидеть, что эти потоки обрабатываются различными потоками, - это добавить в цикл инструкцию sleep . Вы можете попробовать изменить значение, которое вы установили для сна, и посмотреть, что это infact, обрабатываемые разными потоками.

  public class Test {public static void main (String [] args) {for (  int i = 0; i & lt; 10; i ++) {System.out.print ("OUT");  System.err.print («ERR»);  try {Thread.sleep (500);  } catch (InterruptedException e) {e.printStackTrace ();  }}}}  

Выход в этом случае оказался

  OUT ERR ERR OUT ERR OUT OUT ERR OUT ERR ERR OUT OUT ERR ERR OUT  OUT ERR OUT ERR OUT ERR ERR OUT ERR OUT OUT ERR OUT ERR ERR OUT OUT ERR ERR OUT OUT ERR OUT ERR ERR OUT ERR OUT OUT ERR ERR OUT OUT ERR ERR OUT OUT ERR OUT ERR ERR OUT ERR OUT ERR OUT OUT ERR ERR OUT  OUT ERR ERR OUT ERR OUT OUT ERR OUT ERR OUT OUT ERR OUT ERR OUT ERR ERR OUT OUT ERR ERR OUT OUT ERR ERR OUT ERR OUT OUT ERR OUT ERR  

Один из способов заставить его для печати в том же порядке будет использоваться .flush () , который работал для меня. Но это не то, что не все получают с ним правильные результаты.

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

11
задан ruakh 9 March 2012 в 16:34
поделиться

4 ответа

Вы можете сделать это, не прибегая к sed с помощью переменной переменной Bash , хотя, как указывает @ruah, это не будет работать в однострочной версии (без точки с запятой, разделяющей команды) , Я оставляю этот первый подход, потому что я думаю, что интересно, что он не работает в одной строке:

TTY=$(tty); who | grep "${TTY#/dev/}"

Это сначала помещает вывод tty в переменную, а затем стирает /dev/ при использовании grep. Но без точки с запятой TTY это не в среде к моменту bash делает переменное расширение / mangling для grep.

Вот версия, которая работает, потому что она порождает подоболочку с уже измененной средой (с TTY):

TTY=$(tty) WHOLINE=$(who | grep "${TTY#/dev/}")

Результат оставлен в $WHOLINE.

5
ответ дан Eduardo Ivanec 15 August 2018 в 20:32
поделиться
  • 1
    Это не работает: "${TTY#/dev/}" получает слишком рано. Вы должны сделать назначение переменной как отдельную команду (используя разрыв строки или ; или && или еще что-то). – ruakh 9 March 2012 в 16:42
  • 2
    @ruakh: вы правы, это работает только для меня, потому что я уже определил TTY раньше. Благодарю. – Eduardo Ivanec 9 March 2012 в 16:45
  • 3
    @ruakh: добавлена ​​новая версия. – Eduardo Ivanec 9 March 2012 в 16:54
  • 4
    Я хотел найти способ без использования переменной, но это кажется невозможным с учетом проблемы tty + pipe. Я отмечаю это решение как принятое, но другие, где это тоже актуально. (PS: Спасибо за информацию об изменении переменной bash) – CDuv 9 March 2012 в 18:03

Вы можете сделать это следующим образом:

tid=$(tty | sed 's#/dev/##') && who | grep "$tid"
2
ответ дан anubhava 15 August 2018 в 20:32
поделиться

Обычно используется xargs , чтобы сделать вывод одной команды опцией другой команды. Например:

$ cat command1
#!/bin/sh

echo "one"
echo "two"
echo "three"

$ cat command2
#!/bin/sh

printf '1 = %s\n' "$1"

$ ./command1 | xargs -n 1 ./command2
1 = one
1 = two
1 = three
$ 

Но ... пока это был ваш вопрос, это не то, что вы действительно хотите знать.

Если вы не возражаете хранить свой tty в переменную, вы можете использовать переменную bash для замены:

$ tty=`tty`; who | grep -w "${tty#/dev/}"
ghoti            pts/198  Mar  8 17:01 (:0.0)

(вы хотите использовать -w, потому что если вы находитесь на pts / 6, вы не должны видеть лоты pts / 60.)

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

$ true | echo `tty | sed 's:/dev/::'`
not a tty
$ 

Обратите внимание, что ничто в этом ответе пока не относится к bash. Поскольку вы используете bash, другим способом решения этой проблемы является замена процесса. Например, пока это не работает:

$ who | grep "$(tty | sed 's:/dev/::')"

Это делает:

$ grep $(tty | sed 's:/dev/::') < <(who)
8
ответ дан ghoti 15 August 2018 в 20:32
поделиться

Ответ Эдуардо правильный (и, как я писал это, появилось еще несколько хороших ответов), но я хотел бы объяснить, почему исходная команда терпит неудачу. Как обычно, set -x очень полезно видеть, что на самом деле происходит:

$ set -x
$ who | grep $(echo $(tty) | sed 's/\/dev\///')
+ who
++ sed 's/\/dev\///'
+++ tty
++ echo not a tty
+ grep not a tty
grep: a: No such file or directory
grep: tty: No such file or directory

Это не полностью явное из вышеизложенного, но то, что происходит, заключается в том, что tty выводит «не tty». Это связано с тем, что часть конвейера подается на выход who, поэтому его stdin действительно не является tty. Это настоящая причина, по которой все остальные ответы работают: они выходят из tty из-за конвейера, поэтому он может видеть ваш фактический терминал.

BTW, ваша предлагаемая команда в основном правильна (за исключением проблемы с конвейером) , но излишне сложный. Не используйте echo $(tty), это по сути то же самое, что только tty.

5
ответ дан Gordon Davisson 15 August 2018 в 20:32
поделиться
  • 1
    Спасибо за хорошую подсветку «почему это не работает». – CDuv 9 March 2012 в 18:02
Другие вопросы по тегам:

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