Настройка оболочки bash

Я бы хотел настроить свою оболочку bash очень специфическим способом, настолько конкретным, чтобы я не знал, возможно ли это. В настоящее время моя оболочка выглядит следующим образом:

myname@ubuntu /home/myname:
>>

Где myname - мое имя пользователя. Я настроил оболочку со следующей строкой в ​​ ~ / .bashrc :

PS1='${debian_chroot:+($debian_chroot)}\u@\h `pwd`:\n>> '

Когда я нажимаю Enter, вот что происходит:

myname@ubuntu /home/myname:
>>
myname@ubuntu /home/myname:
>>

Вместо этого я хотел бы, чтобы произошло следующее:

myname@ubuntu /home/myname:
>>
>>

Более того, если я наберу команду, что произойдет, должно быть так:

myname@ubuntu /home/myname:
>> echo hello
hello
myname@ubuntu /home/myname:
>>

Следующего не должно произойти

myname@ubuntu /home/myname:
>>echo hello
hello
>>

Возможно ли это? Если да, то как это сделать?

ОБНОВЛЕНИЕ

Я смог достичь своей цели благодаря ответу ChrisAga.

Вот сценарий

# don't put duplicate lines or lines starting with space in the history.
HISTCONTROL=ignoreboth

customprompt() {
    # the current number of lines in bash history:
    bash_history_size=$(fc -l -1)
    bash_history_size=${bash_history_size%%[^0-9]*}

    # set an initial value to the number of lines
    # in bash history stored from the last time
    # this function was executed. This avoids bugs
    # when running the first command in the current
    # shell session
    if [ -n "$bash_history_lastsize" ]; then
        bash_history_lastsize=0
    fi

    # if the current number of lines in bash history
    # is different from the last number of lines, then
    # we print the user name and the current directory.
    # otherwise, we just print >>
    if [ "${bash_history_size}" != "${bash_history_lastsize}" ]; then
        PS1='\[\033[01;32m\]\u@\h \[\033[00m\]`pwd`:\n>> '
    else
        PS1=">> "
    fi

    # update the last value to the current value
    bash_history_lastsize=${bash_history_size}
}

PROMPT_COMMAND=customprompt
2
задан 10 June 2020 в 00:04

2 ответа

На самом деле, существует решение для простого bash!

Единственное ограничение - несовместимость с предотвращением дублирования в команде bash. история. Поэтому, если вы не возражаете против дубликатов в своей истории Bash, вы можете установить следующее в ~ / .bashrc :

HISTCONTROL=ignorespace

function pprompt {
   local hcount=$(fc -l -1)
   echo ${hcount}
   hcount=${hcount%%[^0-9]*}
   if [ "${hcount}" != "${ocount}" ]; then 
      PS1="\[\e]0;\u@\h: \w\a\]\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w:\[\033[00m\]\n>>"
   else 
      PS1=">>"
   fi
   ocount=${hcount}
}

PROMPT_COMMAND=pprompt

По умолчанию HISTCONTROL = ignoreboth , что эквивалентно ignorespace: ignoredups , поэтому вы должны изменить его.

Функция pprompt получает последнюю команду в истории и сравнивает ее номер с ранее сохраненным значением. Если вы просто нажмете, введите число не изменится, поэтому, если это число изменилось, мы устанавливаем PS1 в полное приглашение, в противном случае мы устанавливаем его в >> .

Наконец, PROMPT_COMMAND = pprompt bash для выполнения pprompt перед выводом основного приглашения ( $ PS1 ).

NB1. Если вам не нравится отображать домашний путь как ~ , вы можете заменить \ w на `pwd`.

NB2. Если бы мы могли получить фактический номер команды bash (тот, который мы можем отобразить, используя ! # в приглашении) вместо номера команды истории, мы бы получили решение, совместимое с дедупликацией истории.

2
ответ дан 19 June 2020 в 22:11

Насколько я знаю, вы не можете сделать это просто с помощью простого удара. Но вместо этого вы должны реализовать свою собственную оболочку практически с нуля (не бойтесь, я сделал это, и для этого требуется менее 30 строк кода).

Вот код (custom_shell.sh):

RED='\033[0;31m'                         #Definition of some ASCII colors
WHITE='\033[1;37m'                       #Replace them with whatever color you want

TMP_COMM_BUF="/tmp/custom_shell_buf"     #For temporary storage of commands

if [ "$1" == "e" ]
then 
    printf "${RED}>> ${WHITE}"           #When you just pressed enter
else
    printf  "${RED}$PWD >> ${WHITE} "    #After the execution of some command
fi


exec 3<&1                                #Custom file descriptor
read -u 3 comm_buf                       #Read commands from stdin
echo $comm_buf  > $TMP_COMM_BUF          #Store commands (exec cannot execute multiple commands at once , so we need it)
chmod +x $TMP_COMM_BUF                   #Make it executable
if ! [ -z "$comm_buf" ] 
then
    echo custom_shell.sh >> $TMP_COMM_BUF      #Recover the prompt after the execution ( It's assumed that the name of the file is custom_shell.sh and it's available in the $PATH )
    exec $TMP_COMM_BUF                         #Execute !!!
else
    exec custom_shell.sh e                     #If nothing specified , then just show ">>"
fi

Ограничения:

Поскольку он не может использовать функцию редактирования строки, присутствующую в bash, вы не можете использовать Ctrl + C для прерывания или Ctrl + L для очистки терминала. И нет завершение команды и отсутствие истории оболочки.

Соображения безопасности:

Так как он использует незашифрованный файл ( / tmp / custom_shell_buf ) для хранения команд перед их выполнением, если кто-то просто подделывает их прямо перед фазой исполнения (между строками 16 и 21),

1
ответ дан 19 June 2020 в 22:11

Другие вопросы по тегам:

Похожие вопросы: