bash -c 和非交互式 shell

bash -c 和非交互式 shell

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

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

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

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

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

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

答案1

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

长话短说

非交互式 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 */
}

默认情况下,作业控制处于禁用状态,除非您强制使用-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);
    }

语法错误消息包含行号。

/* 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 ();
...
}

简单测试

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: `;;'

命令执行后不打印提示。

/* 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;

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

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

答案2

在 shell 会话中,有许多选项,例如:

  • 别名是否已扩展
  • 某人/某物正在 STDIN 上打字
  • 完成系统是否已加载
  • 如果命令存储在历史文件中
  • 哪些文件是在 shell 启动时获取的

交互式 shell 是具有其中一些特征的 shell。但是,您可以根据自己的喜好打开或关闭这些选项。可以将这个词视为interactive shell我们通常理解的 shell 交互所需的行为的集合。

当您使用 启动 shell 时-i,它会变得有点混乱,因为它通常表明您正在扰乱系统。其中一些 shell 选项可能具有不同于人们通常理解的交互式 shell 的其他值。

因此,具体而言,您的示例bash -c cat将不会启用完成功能,也不会在历史记录中存储任何内容。我不想这样称呼interactive,但如果您愿意的话,您可以自由地这样做。

答案3

交互式 shell 定义为从 stdin 读取命令的 shell。

通过使用选项“定义”为交互式的非交互式 shell 是否-i读取$ENV文件 ( ~/.*rc) 是未定义的。

相关内容