bash -c 和非交互式 shell

Tim*_*Tim 1 bash

来自https://unix.stackexchange.com/a/276611/674

当 bash 使用 -c 运行时,它被认为是一个非交互式 shell,它不会读取 ~/.bashrc,除非指定了 -i。

  1. 非交互式 shell 是如何定义的?

    • 非交互式 shell 是否定义为不能接受来自 stdin 的输入的 shell?例如bash -c cat可以接受来自标准输入的输入。

    • 非交互式 shell 可以输出到标准输出吗?例如,bash -c date可以写入标准输出。

  2. 是否bash -c(没有附加-i选项)总是创建一个非交互式 shell?

Inc*_*der 6

我做了一些调查。根据bash的源代码。

TL; 博士

非交互式 shell 是如何定义的?

  • 缺少命令历史记录
  • 不支持作业
  • 无行编辑功能
  • 错误获取行号
  • 没有提示
  • 第一个错误后停止执行

bash -c(没有额外的 -i 选项)是否总是创建一个非交互式 shell?

是的

更长的版本。

当 bash 收到-c选项时调用此函数。

no_line_editing = 1 意味着您不能使用退格键来编辑您的命令。

bash_history_reinit (0); 禁用历史记录和命令自动完成。

static void
init_noninteractive ()
{
#if defined (HISTORY)
  bash_history_reinit (0);
#endif /* HISTORY */
  interactive_shell = startup_state = interactive = 0;
  expand_aliases = posixly_correct; /* XXX - was 0 not posixly_correct */
  no_line_editing = 1;
#if defined (JOB_CONTROL)
  /* Even if the shell is not interactive, enable job control if the -i or
     -m option is supplied at startup. */
  set_job_control (forced_interactive||jobs_m_flag);
#endif /* JOB_CONTROL */
}
Run Code Online (Sandbox Code Playgroud)

默认情况下禁用作业控制,除非您强制使用它 -m

 /* We can only have job control if we are interactive unless we                      
force it. */

  if (interactive == 0 && force == 0)
    {
      job_control = 0;
      original_pgrp = NO_PID;
      shell_tty = fileno (stderr);
    }
Run Code Online (Sandbox Code Playgroud)

语法错误消息包含行号。

/* Report a syntax error with line numbers, etc.
   Call here for recoverable errors.  If you have a message to print,
   then place it in MESSAGE, otherwise pass NULL and this will figure
   out an appropriate message for you. */
static void
report_syntax_error (message)
     char *message;
{
...
if (interactive == 0)
print_offending_line ();
...
}
Run Code Online (Sandbox Code Playgroud)

简单测试

root@test:~# ;;
-bash: syntax error near unexpected token `;;'
root@test:~# bash -c ';;'
bash: -c: line 0: syntax error near unexpected token `;;'
bash: -c: line 0: `;;'
Run Code Online (Sandbox Code Playgroud)

命令执行后不打印提示。

/* Issue a prompt, or prepare to issue a prompt when the next character
   is read. */
static void
prompt_again ()
{
  char *temp_prompt;

  if (interactive == 0 || expanding_alias ())   /* XXX */
    return;
Run Code Online (Sandbox Code Playgroud)

第一个错误后命令执行停止。

  /* Parse error, maybe discard rest of stream if not interactive. */
      if (interactive == 0)
        EOF_Reached = EOF;
Run Code Online (Sandbox Code Playgroud)