익명 00:58

Why is Command Prompt, set up via SSH as a Linux terminal and asking for a passw...

Why is Command Prompt, set up via SSH as a Linux terminal and asking for a password, entering 3 or 4 characters when I type a number with NumLock on?

I noticed some strange behavior with Windows Command Prompt while using SSH to connect to a remote Linux server and was wondering if there is an explanation.

I am designing a database on a remote Linux server for company use. Depending on what I am doing, it is sometimes more convenient to edit database-related files by opening Command Prompt, connecting to the remote server, and editing files with commands such as:

PS C:\Users\[username]> ssh [user]@[remote computer name]
Welcome to Ubuntu 26.04 LTS (GNU/Linux 7.0.0-27-generic x86_64)

 * Documentation:  https://docs.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

...

[user]@techadmin-Virtual-Machine:~$ sudo nano /var/www/html/add_raw_material.php
[sudo: authenticate] Password: 

Something strange happens when I have Num Lock enabled and enter numbers using the numeric keypad at this password prompt. With Num Lock on, pressing any digit except 0, 3, or 9 causes three characters to be entered. Pressing 0, 3, or 9 causes four characters to be entered.

All characters displayed in the password prompt appear as "*", so I cannot see what is actually being entered. I can copy the contents, but pasting only produces a series of asterisks regardless of what I typed.

With Num Lock enabled, pressing keys on the numeric keypad does not cause any characters to appear in the normal Command Prompt (when not connected through SSH). It also does not happen when I am SSH-connected and entering commands normally; it only occurs at this Linux sudo password prompt.

Additionally, when I connect directly to the Linux desktop through a remote desktop session, typing numbers with Num Lock enabled behaves normally.

What is causing these extra characters to appear, and what exactly are they?

(I'm on Windows 11, Ubuntu 26.04 LTS (GNU/Linux 7.0.0-27-generic x86_64).)

EDIT: When I type cat -v into CMD (again connected via SSH to the remote server, entering each digit 0-9 with Num Lock on causes the following series of characters to appear:

0: ^[[2~ 1: ^[[F 2: ^[[B 3: ^[[6~ 4: ^[[D 5: ^[[E 6: ^[[C 7: ^[[H 8: ^[[A 9: ^[[5~

I'm assuming these are the characters (probably without the opening ^ to make the number of characters here match the number appearing in the prompt) that are appearing behind the scenes in the password prompt, but what in the world do they signify?

SCREENSHOT WITH NUM LOCK ON: enter image description here

.bashrc:

# ~/.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|*-256color) 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

# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'

# 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

.profile:

# ~/.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

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
    PATH="$HOME/.local/bin:$PATH"
fi


Top Answer/Comment:

In Linux/Unix a non-GUI program you run "in a terminal" does not read keystrokes, it reads input from /dev/tty and/or from its stdin (which may be /dev/tty or something else); these are streams of bytes without intrinsic boundaries. If the program runs under a virtual console then it's the kernel that translates keystrokes to bytes or sequences of bytes. If the program runs under a terminal emulator (which itself is a GUI program) then the terminal emulator gets keystrokes (not directly but still), it translates them to bytes or sequences of bytes programs "within" may read from /dev/tty.

ssh client in Linux is such a "non-GUI program", it knows nothing about keystrokes, it just reads a stream of bytes. I believe ssh run from PowerShell in Windows is similar; but even if it knew about actual keystrokes then this wouldn't matter because SSH (the protocol) is not designed to transmit keystrokes, it transmits streams of bytes. If ssh requests an interactive shell on the remote side (and this is your case; as opposed to running an arbitrary command) then the SSH server allocates a tty for the shell, so the shell (and its descendants, e.g. sudo) can read from /dev/tty and their default stdin is the tty; for them it's like they are run under a terminal (or terminal emulator) that seems local for them.

Whatever you type locally when your local ssh runs and reads input from you, it gets to the remote program(s) as a stream of bytes. Inside the stream a is "encoded" trivially as a, Shift+a is A, Ctrl+p is one byte we denote ^P (ASCII DLE, 0x10), Enter is equivalent to Ctrl+m which is one byte we denote ^M (CR, \r, 0x0d; usually translated at some point to LF, \n, 0x0a), Backspace is ^H (0x08) or ^? (0x7f), Escape is ^[ (ASCII ESC, 0x1b), Ctrl+z is ^Z (note it may or may not get to the remote program(s)). See caret notation.

There are more keystrokes than available characters, so some keystrokes get encoded as sequences of bytes. Usually each such sequence starts with ^[ (one-byte escape character, exactly the one that encodes Escape, not two bytes ^ and [) and for some keystrokes there is more than one convention (and for some there is none).

What you observed when you used cat -v are the sequences for:

  • Insert: ^[[2~
  • End: ^[[F (it may be ^[[4~)
  • : ^[[B
  • PgDn: ^[[6~
  • etc.

Normally with NumLock off your numeric keypad should work as arrows, End, PgDn and such. They get to the remote side as the sequences you observed. With NumLock on your numeric keypad should work as digits, they get to the remote side as one-byte ASCII characters 0, 1, 2 etc.

For a reason I cannot tell your NumLock seems to have reversed or stopped working: you got sequences when (as you claim) your NumLock was on. This is certainly a problem on your local (Windows) side because SSH does not transmit keystrokes and the CLI program(s) on the remote side cannot know the state of your local NumLock, reverse it or be wrong about it; the concept of NumLock simply does not exist for them, they get input as a stream of bytes from your local ssh.

AFAIK a remote desktop session does transmit keystrokes. Maybe to a point where KP_7 (numeric keypad 7) is KP_7 regardless what local computer thinks about the state of the NumLock and gets "translated" to 7 or Home according to what remote computer thinks about the state of the NumLock. I don't know, I cannot verify. But I'm mentioning this because while working with virtual computers and/or VNC in some configurations I observed a phenomenon where pressing NumLock always changed its local state, but the virtual/remote state changed only when the window was in focus at the time. In effect it was possible to desynchronize the two states and make them opposite to each other. If remote desktop allows this or if you in some other way experienced this and therefore believed your NumLock is on because it was on for the virtual/remote OS (and e.g. your keyboard has no light that shows the local state), but for the local OS it was really off then you may have confused (local) off and on states. The local state is what matters for ssh because SSH does not transmit keystrokes.

Anyway, back to the sequences. A program that understands the sequences looks out for them and reacts accordingly. E.g. interactive Bash reacts to (^[[A) and fetches the previous command from the history list. You can even "emulate" by pressing Esc (^[), [, Shift+a fast enough.

This is not a perfect situation, it's historical and there are voices to improve it (example). Still, for now this is how it is.

sudo does not understand the sequences, they are not special to it. The program by default reads password silently but it may be configured to display * for each "character" (with pwfeedback in sudoers). I wrote "character" but it's really * for each byte.

And here you go: each of the sequences your numpad caused when NumLock was (effectively) off is three or four bytes long. sudo reacted to each byte. The connection you made with what cat -v had shown you is basically correct (only "without the opening ^" is wrong; the count is different because ^[ denotes a single byte: ASCII ESC).

상단 광고의 [X] 버튼을 누르면 내용이 보입니다