I am running this on Ubuntu and have tried many variations of exec/spawn functions (and their sync counterparts) and none of them can show me an output for bash 'history' command. One scenario is following:
const { spawnSync} = require('child_process');
const child = spawnSync('history', { shell: "/bin/bash" });
console.log('error: ', child.error);
console.log('stdout: ', child.stdout.toString());
console.log('stderr: ', child.stderr);
It does not show any errors and output is empty. I think this question has more to do with 'specialty' or category of the history command than nodejs's function since they work fine for normal commands like ls, pwd, whoami, etc work fine. I have looked at my .bash_history file and its filled with history so that's not the issue.
Another problem that might be similar is ll
command also fails even though I have set bash as shell. But for ll
, it does return an error:
/bin/bash: ll: command not found
Just to be sure, I tried running ll
command in bash it worked just fine. What am I missing here?
edit: I have done some more testing it seems more like a bash thing than a node thing. When I simply write the history
command, bash prints results but when I do bash -c history
, it does not show any output but also no error.
The bash
(1) man page (see excerpt below) states, that the command history is available when the -o history option is set. The option is on by default, if bash
is in interactive mode. The command line option -i turns interactive mode on. The commands are read from the file designated by the HISTFILE environment variable.
When bash is called with a command via option -c, neither the shell option history is on, nor is the environment variable HISTFILE set:
$ bash -c 'set -o | grep history; shopt -p | grep histappend; echo "HISTFILE: ${HISTFILE-!!not set!!}"'
history off
histappend off
HISTFILE: !!not set!!
When bash is called with the option -i, both the shell option history as well as the environment variable HISTFILE are set:
$ bash -i -c 'set -o | grep history; shopt -p | grep histappend; echo "HISTFILE: ${HISTFILE-!!not set!!}"'
history on
histappend off
HISTFILE: /home/user/.bash_history
Since interactive mode tries to open a terminal - issuing error messages, if that fails - it is better to handle the history setup explicitely:
$bash -c 'unset HISTFILESIZE; HISTFILE="${HOME}/.bash_history"; set -o history; history 5'
496 ls -l
497 ls -l
498 ls -l
499 ls -l
500 ls -l
Note, that the command in interactive mode does not display the history as requested:
$ bash -i -c 'set -o | grep history; echo "HISTFILE: ${HISTFILE-!!not set!!}"; history 5'
history on
HISTFILE: /home/user/.bash_history
It is still necessary to turn the shell option history on explicitely:
$ bash -i -c 'set -o history; history 5'
496 ls -l
497 ls -l
498 ls -l
499 ls -l
500 ls -l
Excerpt from bash
man page:
-c
If the -c option is present, then commands are read from the first non-option argument command_string.
-i
If the -i option is present, the shell is interactive.
[-+]O [ shopt_option ]
shopt_option is one of the shell options accepted by the shopt builtin [...]. If shopt_option is present, -O sets the value of that option; +O unsets it. If shopt_option is not supplied, the names and values of the shell options accepted by shopt are printed on the standard output. If the invocation option is +O, the output is displayed in a format that may be reused as input.
When the -o history option to the set builtin is enabled, the shell provides access to the command history, the list of commands previously typed.
On startup, the history is initialized from the file named by the variable HISTFILE (default ~/.bash_history). The file named by the value of HISTFILE is truncated, if necessary, to contain no more than the number of lines specified by the value of HISTFILESIZE. If HISTFILESIZE is unset, or set to null, a non-numeric value, or a numeric value less than zero, the history file is not truncated.
set -o option-name
The option-name can be one of the following:
history
Enable command history, as described above under HISTORY. This option is on by default in interactive shells.
If -o is supplied with no option-name, the values of the current options are printed. If +o is supplied with no option-name, a series of set commands to recreate the current option settings is displayed on the standard output.