"♦: command not found" in tty after login
Solution 1
Workaround
First, I think that you refer about when you go in tty1 - Ctrl + Alt + F1.
Now, I think is happening what you said most likely because you have a strange character like ♦ (diamond suit character or the special badge for an askubuntu moderator) in ~/.bashrc
or ~/.profile
file or other file that contain various initialization commands.
As you can see in next image, I edited ~/.bashrc
file puting inside ♦ character on a single line. As result, when I open the terminal it get the problem described by you:
It is happening the same when I go in tty1 with Ctrl + Alt + F1.
Files that contain initialization commands when a shell is invoked: /etc/profile
, /etc/bashrc
, ~/.bash_login
, ~/.profile
, ~/.bashrc
, ~/.bash_aliases
and maybe others. See Shell initialization files.
To quickly check if one of these files have something wrong inside you can use source
command. For example:
source ~/.bashrc
Final solution
After inspecting /etc/profile
from http://paste.ubuntu.com/5781361/, I found that on the line 31 there is "Right-To-Left Override" - ‮
unicode character. Just open /etc/profile
file with sudo -H gedit /etc/profile
, make sure to delete this strange character and the problem will disappear.
As amusement, in HTML for example, if you insert this unicode character using decimal code (‮
) in front of a line, look what is happening:
This text is in arabic-english!
Another more generalized solution
We will find the exact command that causing the error using a "trap".
First, we have to make a new script file in ~/bin
directory, let's call it lib.trap.sh
(gedit ~/bin/lib.trap.sh
), with following inside:
lib_name='trap'
lib_version=20130620
#changed from lib_version=20121026 found it at https://stackoverflow.com/a/13099228/2353900 to work well at initialization of the shell
stderr_log="/dev/shm/stderr.log"
#
# TO BE SOURCED ONLY ONCE:
#
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
if test "${g_libs[$lib_name]+_}"; then
return 0
else
if test ${#g_libs[@]} == 0; then
declare -A g_libs
fi
g_libs[$lib_name]=$lib_version
fi
#
# MAIN CODE:
#
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
set -o pipefail # trace ERR through pipes
set -o errtrace # trace ERR through 'time command' and other functions
set -o nounset ## set -u : exit the script if you try to use an uninitialised variable
set -o errexit ## set -e : exit the script if any statement returns a non-true return value
exec 2>"$stderr_log"
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
#
# FUNCTION: EXIT_HANDLER
#
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
function exit_handler ()
{
local error_code="$?"
test $error_code == 0 && return;
#
# LOCAL VARIABLES:
# ------------------------------------------------------------------
#
local i=0
local regex=''
local mem=''
local error_file=''
local error_lineno=''
local error_message='unknown'
local lineno=''
#
# PRINT THE HEADER:
# ------------------------------------------------------------------
#
# Color the output if it's an interactive terminal
test -t 1 && tput bold; tput setf 4 ## red bold
echo -e "\n(!) EXIT HANDLER\n"
#
# GETTING LAST ERROR OCCURRED:
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
#
# Read last file from the error log
# ------------------------------------------------------------------
#
if test -f "$stderr_log"
then
stderr=$( tail -n 1 "$stderr_log" )
rm "$stderr_log"
fi
#
# Managing the line to extract information:
# ------------------------------------------------------------------
#
if test -n "$stderr"
then
# Exploding stderr on :
mem="$IFS"
local shrunk_stderr=$( echo "$stderr" | sed 's/\: /\:/g' )
IFS=':'
local stderr_parts=( $shrunk_stderr )
IFS="$mem"
# Storing information on the error
error_file="${stderr_parts[0]}"
error_lineno="${stderr_parts[1]}"
error_message=""
for (( i = 3; i <= ${#stderr_parts[@]}; i++ ))
do
error_message="$error_message "${stderr_parts[$i-1]}": "
done
# Removing last ':' (colon character)
error_message="${error_message%:*}"
# Trim
error_message="$( echo "$error_message" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//' )"
fi
#
# GETTING BACKTRACE:
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
_backtrace=$( backtrace 2 )
#
# MANAGING THE OUTPUT:
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
local lineno=""
regex='^([a-z]{1,}) ([0-9]{1,})$'
if [[ $error_lineno =~ $regex ]]
# The error line was found on the log
# (e.g. type 'ff' without quotes wherever)
# --------------------------------------------------------------
then
local row="${BASH_REMATCH[1]}"
lineno="${BASH_REMATCH[2]}"
echo -e "FILE:\t\t${error_file}"
echo -e "${row^^}:\t\t${lineno}\n"
echo -e "ERROR CODE:\t${error_code}"
test -t 1 && tput setf 6 ## white yellow
echo -e "ERROR MESSAGE:\n$error_message"
else
regex="^${error_file}\$|^${error_file}\s+|\s+${error_file}\s+|\s+${error_file}\$"
if [[ "$_backtrace" =~ $regex ]]
# The file was found on the log but not the error line
# (could not reproduce this case so far)
# ------------------------------------------------------
then
echo -e "FILE:\t\t$error_file"
echo -e "ROW:\t\tunknown\n"
echo -e "ERROR CODE:\t${error_code}"
test -t 1 && tput setf 6 ## white yellow
echo -e "ERROR MESSAGE:\n${stderr}"
# Neither the error line nor the error file was found on the log
# (e.g. type 'cp ffd fdf' without quotes wherever)
# ------------------------------------------------------
else
#
# The error file is the first on backtrace list:
# Exploding backtrace on newlines
mem=$IFS
IFS='
'
#
# Substring: I keep only the carriage return
# (others needed only for tabbing purpose)
IFS=${IFS:0:1}
local lines=( $_backtrace )
IFS=$mem
error_file=""
if test -n "${lines[1]}"
then
array=( ${lines[1]} )
for (( i=2; i<${#array[@]}; i++ ))
do
error_file="$error_file ${array[$i]}"
done
# Trim
error_file="$( echo "$error_file" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//' )"
fi
echo -e "ROW, FILE:\t\t${lines[2] }\n"
echo -e "ERROR CODE:\t${error_code}"
test -t 1 && tput setf 6 ## white yellow
if test -n "${stderr}"
then
echo -e "ERROR MESSAGE:\n${stderr}"
else
echo -e "ERROR MESSAGE:\n${error_message}"
fi
fi
fi
#
# PRINTING THE BACKTRACE:
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
test -t 1 && tput setf 7 ## white bold
echo -e "\n$_backtrace\n"
#
# EXITING:
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
test -t 1 && tput setf 4 ## red bold
echo "Exiting!"
test -t 1 && tput sgr0 # Reset terminal
exit "$error_code"
}
trap exit_handler ERR # ! ! ! TRAP EXIT ! ! !
#trap exit ERR # ! ! ! TRAP ERR ! ! !
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
#
# FUNCTION: BACKTRACE
#
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
function backtrace
{
local _start_from_=0
local params=( "$@" )
if (( "${#params[@]}" >= "1" ))
then
_start_from_="$1"
fi
local i=0
local first=false
while caller $i > /dev/null
do
if test -n "$_start_from_" && (( "$i" + 1 >= "$_start_from_" ))
then
if test "$first" == false
then
echo "BACKTRACE IS:"
first=true
fi
caller $i
fi
let "i=i+1"
done
}
return 0
Now, the only thing what you have to do is to put next line at the begining of the file /etc/profile
(sudo -H gedit /etc/profile
):
source '/home/<user_name>/bin/lib.trap.sh'
Change <user_name>
with your user name. Like this, all the files that contain initialization commands when a shell is invoked will pass through the "trap".
To test if there is a wrong command in /etc/profile
for example, run in terminal next commands:
bash source /etc/profile
If something is wrong, like in this case, the result will be:
So, now we know for sure that there is a problem (command not found
) in /etc/profile
file at line 32 (it is not at the line 31 as above because we have inserted a new line at the beginning of the file).
Many thanks to Luca Borrione for his script from this answer that helped me to complete this generalized solution.
Solution 2
For debugging the initialization scripts of bash, run the following (after having logged in at the virtual console).
PS4='+ $BASH_SOURCE:$LINENO:' bash -xlic ''
The above runs bash in interactive (-i
) login (-l
) mode, the same as the login
program does when you log into a virtual console. -c ''
makes it exit immediately after running through the initialization scripts, and the -x
and PS4=...
makes it output each command, before it runs them, along with the filename and line number of that command. That should help determining which line of which file that invalid command resides.
On a side note, ♦ is the symbol the default font for the virtual console uses to print characters it does not have a symbol for.
Solution 3
While searching your initialization files, it may be helpful to look for the hexadecimal used for outputting the ♦. The hex code for ♦ is 2666, according to Unicode Character 'BLACK DIAMOND SUIT' . Note: There is at least one other hex code, 25C6, which produces the same or similar looking symbol. See the search results for "diamond". Unicode Character Search
Perhaps something like \u2666
is in one of the scripts. From Bash Reference Manual for echo - "\uhhhh the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHH (one to four hex digits)"
It depends on the character encoding used, so you may want to search the most likely ones first. echo $LC_CTYPE
should return the character encoding used by your shell. See How to get terminal's Character Encoding
Related videos on Youtube
Vitaly Zdanevich
Updated on September 18, 2022Comments
-
Vitaly Zdanevich over 1 year
I have this problem after upgrade Lubuntu from 12.10 to 13.04.
I press Ctrl + Alt + 1, enter login, password, wait two seconds and get:
♦: command not found"
. After this message I can type commands without problems, but what is it?echo $PATH /usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/vitaly/bin:/usr/java/jdk1.7.0_17/bin
My
.bashrc
file is:# ~/.bashrc: executed by bash(1) for non-login shells. # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) # for examples # If not running interactively, don't do anything case $- in *i*) ;; *) return;; esac # don't put duplicate lines or lines starting with space in the history. # See bash(1) for more options HISTCONTROL=ignoreboth # append to the history file, don't overwrite it shopt -s histappend # for setting history length see HISTSIZE and HISTFILESIZE in bash(1) HISTSIZE=1000 HISTFILESIZE=2000 # check the window size after each command and, if necessary, # update the values of LINES and COLUMNS. shopt -s checkwinsize # If set, the pattern "**" used in a pathname expansion context will # match all files and zero or more directories and subdirectories. #shopt -s globstar # make less more friendly for non-text input files, see lesspipe(1) [ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" # set variable identifying the chroot you work in (used in the prompt below) if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then debian_chroot=$(cat /etc/debian_chroot) fi # set a fancy prompt (non-color, unless we know we "want" color) case "$TERM" in xterm-color) color_prompt=yes;; esac # uncomment for a colored prompt, if the terminal has the capability; turned # off by default to not distract the user: the focus in a terminal window # should be on the output of commands, not on the prompt #force_color_prompt=yes if [ -n "$force_color_prompt" ]; then if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then # We have color support; assume it's compliant with Ecma-48 # (ISO/IEC-6429). (Lack of such support is extremely rare, and such # a case would tend to support setf rather than setaf.) color_prompt=yes else color_prompt= fi fi if [ "$color_prompt" = yes ]; then PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' else PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' fi unset color_prompt force_color_prompt # If this is an xterm set the title to user@host:dir case "$TERM" in xterm*|rxvt*) PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" ;; *) ;; esac # enable color support of ls and also add handy aliases if [ -x /usr/bin/dircolors ]; then test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" alias ls='ls --color=auto' #alias dir='dir --color=auto' #alias vdir='vdir --color=auto' alias grep='grep --color=auto' alias fgrep='fgrep --color=auto' alias egrep='egrep --color=auto' fi # some more ls aliases alias ll='ls -alF' alias la='ls -A' alias l='ls -CF' # Add an "alert" alias for long running commands. Use like so: # sleep 10; alert alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' # Alias definitions. # You may want to put all your additions into a separate file like # ~/.bash_aliases, instead of adding them here directly. # See /usr/share/doc/bash-doc/examples in the bash-doc package. if [ -f ~/.bash_aliases ]; then . ~/.bash_aliases fi # enable programmable completion features (you don't need to enable # this, if it's already enabled in /etc/bash.bashrc and /etc/profile # sources /etc/bash.bashrc). if ! shopt -oq posix; then if [ -f /usr/share/bash-completion/bash_completion ]; then . /usr/share/bash-completion/bash_completion elif [ -f /etc/bash_completion ]; then . /etc/bash_completion fi fi
My
.profile
file is:# ~/.profile: executed by the command interpreter for login shells. # This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login # exists. # see /usr/share/doc/bash/examples/startup-files for examples. # the files are located in the bash-doc package. # the default umask is set in /etc/profile; for setting the umask # for ssh logins, install and configure the libpam-umask package. #umask 022 # if running bash 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
The file
/etc/profile
is here: http://paste.ubuntu.com/5781361/ -
Vitaly Zdanevich almost 11 yearsAdded code from
.bashrc
and.profile
to question - I can't find ♦ here. -
Radu Rădeanu almost 11 years@VitalyZdanevich You should check all the files that contain initialization commands (
.bash_aliases
,.pam_environment
, etc) for somenthing strange inside, not necessarily exactly this character. -
Radu Rădeanu almost 11 years@VitalyZdanevich Check also
/etc/profile
and/etc/bashrc
files. Also, I edited my answer. -
Radu Rădeanu almost 11 years-1 because in
~/.bash_history
are stored the commands runned interactive on PS1. -
iyrin almost 11 yearsThank you for confirming. I have removed it. Should I have added the rest as a comment to your answer, Radu?
-
Vitaly Zdanevich almost 11 yearsOh, I don't understand - what I need to do? Where in Lubuntu initialization files? I tried full-text search for
\u2666
and ♦ in Catfish (Lubuntu search) - nothing. I sowhistory
- nothing. I see this message only in tty only after login. Afterecho $LC_CTYPE
I get empty line. -
Vitaly Zdanevich almost 11 yearsAfter
source /etc/profile
I get: command not found
. My `/etc/profile here - paste.ubuntu.com/5781361 -
Radu Rădeanu almost 11 yearsYes, the problem is on the line 31 from
/etc/profile
. You have something very strange there. Just delete everithing betwenfi
andJAVA_HOME
, after press one or two 'Enter' and everything should be ok after. Modify the file withsudo gedit /etc/profile
-
iyrin almost 11 yearsWhere do you see this in his
/etc/profile
? I don't see the rlo in the pastebin or its html source. -
Radu Rădeanu almost 11 years@RyanLoremIpsum In Chromium, select line 31 from paste.ubuntu.com/5781361, right click and select 'Inspect Element'. You will get the result from my last image from the answer.
-
iyrin almost 11 yearsGot it! Thanks. Do you suspect that the rlo is causing his shell to output the diamond be reading something from right to left?
-
iyrin almost 11 yearsRunning
locale
should show the LC_CTYPE. locale -
iyrin almost 11 yearsTry Radu's answer before this one! If we narrow down the character set used in your tty, you can search for the occurrence of the corresponding character code for the solid diamond. This search would prove to be fruitless if Radu's RLO find is cause tho.
-
Radu Rădeanu almost 11 years@RyanLoremIpsum No, I'm sure. The OP had pasted there, not me :)
-
Vitaly Zdanevich almost 11 yearsGreat! I clear this two transparent lines in
/etc/profile
. Strange bag. -
iyrin almost 11 yearsPerhaps it appeared as transparent in your editor because RLO shouldn't output a character. Anyway, that was Radu's bounty so pay up. :)