Is there a difference between /etc/profile and a bash init file? - bash

I am trying to extend my bash history size from 1000 commands to 10000 commands.
I am trying to follow this tutorial to extend my bash history from 1000 commands to 10000. In the first paragraph, it says to append the following three lines to my 'bash init.'
export HISTCONTROL=erasedups
export HISTSIZE=10000
shopt -s histappend
Google lead me to the bash beginner guide and I can't read it, since Bash isn't my first language. I think the following excerpt answers my question, but I'm not sure.
When invoked interactively with the --login option or when invoked as sh, Bash reads the /etc/profile instructions. These usually set the shell variables PATH, USER, MAIL, HOSTNAME and HISTSIZE.
Questions I have:
Am I reading this right when I assume that /etc/profile is the same as a bash initialize?
How can I test if this worked? /etc/profile currently looks like this:
export HISTSIZE=10000
shopt -s histappend
# System-wide .profile for sh(1)
if [ -x /usr/libexec/path_helper ]; then
eval `/usr/libexec/path_helper -s`
fi
if [ "${BASH-no}" != "no" ]; then
[ -r /etc/bashrc ] && . /etc/bashrc
fi
Update: putting those commands in the bashrc didn't seem to do anything, but following this add timestamps to bash history tutorial, I put the commands in /etc/bashrc . My history now has timestamps. Is it safe to assume that .bash_history now saves 100000 commands as well?

Bash may read several different files. Since these are bash specific options that don't work for sh, you should put them in ~/.bashrc and make sure you have a line source ~/.bashrc in ~/.bash_profile.
You can test it by opening a new terminal and running echo $HISTCONTROL and shopt histappend to see whether they have the expected values ("erasedups" and "on").

Related

Bash completion does not work in ZSH/Oh-My-ZSH because COMP_WORDS is not an array

I'm writing a bash command line tool for which I want to enable bash completion using completely.
I have the following bash completion. After I eval "$(./cli completion)" (which outputs the below), completions work fine in bash:
#!/usr/bin/env bash
# This bash completions script was generated by
# completely (https://github.com/dannyben/completely)
# Modifying it manually is not recommended
_cli_completions() {
local cur=${COMP_WORDS[COMP_CWORD]}
local comp_line="${COMP_WORDS[*]:1}"
case "$comp_line" in
'completions'*) COMPREPLY=($(compgen -W "--help -h" -- "$cur")) ;;
'download'*) COMPREPLY=($(compgen -W "--force --help -f -h" -- "$cur")) ;;
''*) COMPREPLY=($(compgen -W "--help --version -h -v completions download" -- "$cur")) ;;
esac
}
complete -F _cli_completions cli
However, they do not work right in ZSH. I have identified the problem to be that COMP_WORDS is not an array when I'm inside ZSH, but it is inside bash. This then breaks the line local comp_line="${COMP_WORDS[*]:1}".
E.g. in the situation ./cli download <tab>, comp_line should be download, but in ZSH it's /cli download (only the . is removed), so I always end up in the last case ''*.
I'm using ZSH 5.8 with Oh-My-ZSH. Bash completions generally seem to work in ZSH.
Oh-My-ZSH sets up completions using
fpath=($ZSH/functions $ZSH/completions $fpath)
autoload -U compaudit compinit
I have tried setting setopt shwordsplit, hoping that that would cause COMP_WORDS to be treated as an array, but it had no effect.
Is there a ZSH configuration that I can change to make this completion script work?
Or is there a bash compatible change to the completion script that would make it work in both shells?
This issue is discussed in this Github ticket.
ZSH should be totally capable of handling bash completions when it is configured to do so by adding these two lines in ~/.zshrc:
# Load bash completion functions
autoload -Uz +X compinit && compinit
autoload -Uz +X bashcompinit && bashcompinit
In addition, the script in question, generated by the completely gem, seems to have a problem.
Replacing * with # in the below line seems to make it work on both bash and zsh.
local comp_line="${COMP_WORDS[*]:1}" # broken
local comp_line="${COMP_WORDS[#]:1}" # works

Weird combination of numbers and letters in front of terminal prompt macOS

Curious as to why I have the sequence : h-63-4 in front of my terminal prompt.
Example: (base) h-63-4:~ axel$
Screenshot
I believe I was messing around with virtual environments in python when it first started appearing, but haven't been able to figure out as to what's causing it.
Contents of my .bashrc:
# System-wide .bashrc file for interactive bash(1) shells.
if [ -z "$PS1" ]; then
return
fi
PS1='\h:\W \u\$ '
# Make bash check its window size after a process completes
shopt -s checkwinsize
[ -r "/etc/bashrc_$TERM_PROGRAM" ] && . "/etc/bashrc_$TERM_PROGRAM"

Bash: Output all aliases and functions in a script

Take the following script:
shopt -s expand_aliases
set -f
result=$(compgen -A function)
echo $result
When running it outputs all my custom bash functions:
mp3gain pkg-pkgbuild-download quote quote_readline restart standby turnoff turnoff-timer youtubeConvert
However, when slightly changing the script to output aliases, the output is empty:
shopt -s expand_aliases
set -f
result=$(compgen -A alias)
echo $result
Yet it is not empty if I run compgen -A alias directly.
My aliases are stored in ~/.bash_aliases and my functions in /.bash_functions. Both are sources in ~/.bashrc:
# Functions
if [ -f ~/.bash_functions ]; then
. ~/.bash_functions
fi
# Aliases
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
What am I missing here?
I'd be willing to wager that the aliases are not sourced. This can be verified running this simple script:
#!/bin/bash
alias
If there is no output, the aliases are not sourced. Hence, that's why compgen returns an empty list when put in a script (non-sourced aliases) but works fine when run manually in a shell with sourced aliases.
Solution: put "source ~/.bash_aliases" near the top of your script to make sure they are invoked before running.

-bash ruby command not found

Every time I log into my VPS I must run source ~/.bashrc before I can run any rvm, ruby, or gem commands.
Why is this? Can't make it load by default?
ssh deployer#xxx
ruby -v
-bash: ruby: command not found
source ~/.bashrc
ruby -v
ruby 1.9.3p429 (2013-05-15 revision 40747) [i686-linux]
I installed rvm under deployer.
I have ~/.bash_pofile which is empty. I also have ~/.profile which has the following in it:
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
My ~/.bashrc has this at the top:
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
From the bash man page:
When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.
So in your case, the (empty) ~/.bash_profile is being executed, and your ~/.profile (and thus your ~/.bashrc) are ignored. To solve this, you'll either need to delete your ~/.bash_profile, or else move the contents of ~/.profile into ~/.bash_profile.
When you log in, if Bash can find a file named .bash_profile in your home directory it will execute it and do not even search for a .profile file. Thus you have two choices, either remove the empty .bash_profile file or copy the contents of .profile to .bash_profile.
Moving the information from .bashrc to the other files, as suggested by others is one way to do it.
Otherwise, this snippet of code will do the same thing, without needing to move the contents, or remove the file. Depending on the ways you have things set up, you may not want to delete a file, if it has relevant information in it for other tasks, other than interactive login.
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
Though using the files as they are intended to be used by reading the documentation can definitely alleviate some frustration.

ssh command execution doesn't consider .bashrc | .bash_login | .ssh/rc? [duplicate]

This question already has answers here:
Why aliases in a non-interactive Bash shell do not work
(4 answers)
Closed 6 years ago.
I am trying to execute a command remotely over ssh, example:
ssh <user>#<host> <command>
The command which needs to be executed is an alias, which is defined in .bashrc, e.g.
alias ll='ls -al'
So what in the end the following command should get executed:
ssh user#host "ll"
I already found out that .bashrc only gets sourced with interactive shell, so in .bash_login I put:
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
and I also tried to define the alias directly in .bash_login.
I also tried to put the alias definition / sourcing of .bashrc in .bash_profile and also in .ssh/rc. But nothing of this works.
Note that I am not able to change how the ssh command is invoked since this is a part of some binary installation script. The only thing I can modify is the environment. Is there any other possibility to get this alias sourced when the ssh command is executed? Is there some ssh configuration which has to be adapted?
From the man pages of bash:
Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt
There are a couple ways to do this, but the simplest is to just add the following line to your .bashrc file:
shopt -s expand_aliases
Instead of:
ssh user#host "bash -c ll"
try:
ssh user#host "bash -ic ll"
to force bash to use an "interactive shell".
EDIT:
As pointed out here about non-interactive shells..
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
# execution returns after this line
Now, for every alias in your bashrc file say i have:
alias ll="ls -l"
alias cls="clear;ls"
Create a file named after that alias say for ll:
user#host$ vi ssh_aliases/ll
#inside ll,write
ls -l
user#host$ chmod a+x ll
Now edit .bashrc to include:
# If not running interactively, don't do anything
[ -z "$PS1" ] && export $PATH=$PATH:~/ssh_aliases
This does the job.. although I am not sure if it is the best way to do so
EDIT(2)
You only need to do this for aliases, other commands in bashrc will be executed as pointed out by David "you must have executable for ssh to run commands".
an alternative to alias that will be visible in all script is
EXPORT & EXECUTE VARIABLE
# shortcut to set enviroment to insensitive case
export go_I="shopt -s nocasematch"
Now in any script you can use
#!/bin/bash
$go_I # go Insensitive
[[ a == A ]] # evaluates TRUE ( $? == 0)
$go_C # maibe want to go back to casesensitive
it's useful to place all shortcuts/aliases in /path/to/my_commands and edit /etc/bash.bashrc
source /path/to/my_commands
Open file ~/.bash_profile. If this file does not exist create one in the home directory and add the below line
source = $HOME/.bashrc
exit your ssh and login agian and you should get the .bashrc settings working for you.

Resources