0

This question already has an answer here:

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

When bash is run with -c, it is considered a non-interactive shell, and it does not read ~/.bashrc, unless is -i specified.

  1. How is a non-interactive shell defined?

    • Is a non-interactive shell defined as a shell which can't accept input from stdin? For example bash -c cat can accept input from stdin.

    • Can a non-interactive shell output to stdout? For example, bash -c date can write to stdout.

  2. Does bash -c (without additional -i option) always create a non-interactive shell?

marked as duplicate by Eric Renouf, Gilles bash Apr 17 '16 at 22:14

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • I think you're overanalyzing it a little. – PSkocik Apr 17 '16 at 20:35
  • 1
    Did you read man bash | grep -C5 -i interactive? – Lucas Apr 17 '16 at 20:48
  • Yes. @Lucas. I am not asking about how to start an interactive shell, and how to do a thing or two under an interactive shell. I am asking about its definition, or less accurately, what it means. – Tim Apr 17 '16 at 20:56
  • 1
    The manual is pretty clear: LESS=+/'An interactive shell' man bash. I suggest that you read it. – user79743 Apr 17 '16 at 22:21
4

I made some investigations. According to the source code of bash.

TL;DR

How is a non-interactive shell defined?

  • lack of commands history
  • jobs are not supported
  • no line editing feature
  • errors gets line number
  • no prompt
  • execution is stopped after first error

Does bash -c (without additional -i option) always create a non-interactive shell?

Yes

Longer version.

This function is called when bash receives -c option.

no_line_editing = 1 means that you can't edit your commands by using backspace.

bash_history_reinit (0); disables the history and commands auto completion.

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

Job control is disabled by default unless you force it with -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);
    }

Syntax error messages contains line numbers.

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

Simple test

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

Prompt is not printed after command execution.

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

Command execution is stopped after first error.

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

Within a shell session, there are a number of options on or of, like:

  • are aliases are expanded
  • is someone/something typing on STDIN
  • is the completion system loaded
  • if commands are stored in a history file
  • which files files are sourced at the start of the shell

An interactive shell is a shell that has some of these characteristics. You can, however, switch those options on or off to your liking. Think of the word interactive shell as a collection of behaviors that we commonly understand to need for a shell to be interactive.

When you start a shell with -i, it gets a bit messy, as it generally indicates that you are messing with the system. It might be that some of these shell options will have another value than what one normally understands as an interactive shell.

So concretely, your example bash -c cat will not have completion enabled, will not store anything in history. I would not want to call that interactive, but you are free to do that if you would so incline.

1

An interactive shell is defined as a shell that reads commands from stdin.

Whether or not a non-interactive shell that is "defined" to be interactive by using the -i option reads the $ENV file (~/.*rc) is undefined.

  • Thanks. Is the shell created by bash -i -c interactive or non-interactive? Also see the example bash -c -i "cp .file1 file2" and bash -c "cp .file1 file2" in unix.stackexchange.com/a/276611/674 – Tim Apr 18 '16 at 4:53
  • The difference is a result of the fact that bash seems to read $ENV in case it is called with the -i option. Inside the $ENV file, there seem to be alias definitions for cp that replace cp by something like cp -i. BTW: there is currently a discussion whether POSIX should forbid aliases to be turned on in scripts with POSIX issue 8 that will start it's development around autumn 2016. – schily Apr 18 '16 at 11:48

Not the answer you're looking for? Browse other questions tagged or ask your own question.