내 목표는 다중 터미널 환경을 시작하는 것입니다.
- 키보드 키를 누르는 것처럼 한 번에 모든 터미널에 쉽게 액세스할 수 있습니다(yakuake 및 guake를 사용하여 이 작업을 수행할 수 있습니다).
- 항목이 어디에 있는지 알 수 있도록 맞춤 이름이 붙은 탭
- 미리 실행된 전체 명령으로 멀티탭 터미널을 실행하여 각 탭 터미널에 대한 완전한 설정 환경을 갖출 수 있습니다.
오늘은 무엇을 하나요?
guake를 열었는데 yakuake보다 RAM을 적게 사용합니다.
F5와 같은 키를 누르고 개발을 위한 기본 환경을 시작할 수 있도록 Bash에 일부 키 바인딩이 구성되어 있으므로 여전히 각 특정 터미널에 대해 F5를 눌러야 합니다.
여전히 5개 탭 각각에 특정 명령을 입력해야 합니다.
또한 어떤 특정 명령을 실행할지 알 수 있도록 이전에 이름을 지정했습니다.
연구:
- 멀티탭 단자 : 야쿠아케, 과케,미스터 xvt.
- 이름 변경 가능한 탭: guake, yakuake. 하지만 mrxvt에 대한 방법을 찾을 수 없습니다.
- 우리가 사용할 수 있다는 걸 알아요버스 탭 이름 변경 등 yakuake를 사용하여 많은 작업을 수행할 수 있습니다. guac에 대해 잘 모르겠습니다. mrxvt를 사용하여 탭 이름을 변경하는 방법을 찾을 수 없습니다.
최종 결과를 얻으려면 간접적인 방법(명령줄이 필요하지 않고 qdbus를 통할 수 있음)이면 충분합니다. 몇 가지 스크립트를 준비하면 됩니다.
가장 낮은 RAM(mrxvt)을 사용하는 애플리케이션도 실행 중인 다른 애플리케이션을 처리하는 데 중요하지만 이를 사용하여 목표를 달성할 수 없다면 소용이 없습니다.
답변1
"다중 터미널" 환경을 찾고 있다면 터미널 자체를 찾는 것이 아니라(터미네이터가 좋은 선택입니다) 대신 터미널 멀티플렉서에 대한 경로를 확인하는 것이 좋습니다 tmux
.
이를 통해 tmux
고급 터미널의 모든 장점을 누릴 수 있을 뿐만 아니라 모든 터미널과 원격 서버에서도 사용할 수 있습니다.
tmux
또 다른 장점은 터미널을 닫아도 TMUX 세션이 여전히 존재하고 재개할 수 있으며 모든 vim 파일, o 프로그램 및 ssh 세션이 여전히 실행 중이라는 것입니다.
미리 정의된 TABS(tmux의 창)를 사용하여 여러 터미널을 구성하고 일부 명령을 자동으로 실행하기 위해 tmux
tmuxinator(https://github.com/tmuxinator/tmuxinator) 및 tmuxp(https://tmuxp.git-pull.com/)
tmuxp 예
session_name: 4-pane-split
start_directory: ./ # load session relative to config location (project root).
before_script: ./.tmuxp-before-script.sh
shell_command_before:
- '[ -f .venv/bin/activate ] && source .venv/bin/activate && reset'
windows:
- window_name: dev window
layout: tiled
shell_command_before:
- cd ~/ # run as a first command in all panes
panes:
- shell_command: # pane no. 1
- cd /var/log # run multiple commands in this pane
- ls -al | grep \.log
- echo second pane # pane no. 2
- echo third pane # pane no. 3
- echo forth pane # pane no. 4
- window_name: docs
layout: main-horizontal
options:
main-pane-height: 35
start_directory: docs/
panes:
- focus: true
- pane
- make serve
- make SPHINXBUILD='poetry run sphinx-build' watch
일부 링크:
답변2
guake 버전 >= 3.8.5-1인 경우 다음이 필요합니다. (
cat >>bashAutoCmdOnStart.sh
그리고 이 명령을 ~/.bashrc 끝에 추가합니다.)
#!/bin/bash
strFlBase="/tmp/`basename "$0"`."
if [[ "$1" == "--getExecFileForUID" ]];then
shift
echo "Showing id for current term on guake:" >&2
echo "${strFlBase}$1"
exit 0
fi
#TODO for yakuake too
if [[ -z "$GUAKE_TAB_UUID" ]];then declare -p GUAKE_TAB_UUID;exit 0;fi
: ${bBashAutoCmdOnStart:=true} #help
if ! $bBashAutoCmdOnStart;then ps;pwd;declare -p bBashAutoCmdOnStart;exit 0;fi
ps;pwd
strFlExec="${strFlBase}$GUAKE_TAB_UUID"
nCount=0
while true;do
echo -ne "$SECONDS: wating terminal auto cmd ($strFlExec). Hit any key for prompt.\r";
#TODO test if terminal is interactive, I think `read` is failing when guake loads initially on pc restart
if read -t 3 -n 1;then break;fi;
if [[ -f "$strFlExec" ]];then
echo "EXECUTING file contents '$strFlExec' here:"
cat "$strFlExec"
strRunFl="${strFlExec}.Running.${nCount}"
mv -v "$strFlExec" "$strRunFl"
#chmod +x "${strFlExec}.Running"
source "${strRunFl}"
ps;pwd
#bash -c "${strFlExec}.Running;ps;pwd;bash"
((nCount++))&&:
fi
done
ps;pwd
bBashAutoCmdOnStart=false bash
예제를 실행하려면: guakeAutoEnv.sh [-x] -ID_CMD workA ls 123 -ID_CMD workB ls 456 789
#-x는 (현재 guake 탭 대신) xterm에서 실행하는 것입니다.
cat >>guakeAutoEnv.sh
#!/bin/bash
nWId="`wmctrl -l |grep "Guake!" |awk '{print $1}'`";declare -p nWId
: ${bUseBashAutoCmdMode:=false}
if ! qdbus org.guake3.RemoteControl /org/guake3/RemoteControl |grep execute_command_by_uuid;then
#echoc --alert "@{-n}execute_command_by_uuid was @nremoved@{-n}, therefore this script wont work that way anymore :(";
bUseBashAutoCmdMode=true
fi
if [[ -z "${1-}" ]] || [[ "${1}" == --help ]];then
#help Usage ex.: [-x] -ID_CMD coolName ls 123 -ID_CMD funnyName ls 456 789
egrep "[#]help" $0 |sed -r -e 's"^[[:space:]]*""' -e 's"[[:space:]]*$""' >/dev/stderr
exit 0
fi
export bUsingXtermToRun=false;
if [[ "${1-}" == "-x" ]];then
bUsingXtermToRun=true;
shift&&:;
(xterm -e $0 "$@"&disown) #w/o -x now
exit
fi
set -Eeu
# depends on
while ! pgrep -fa "`which guake`";do echo " >>>>> WARN:WaitingGuakeStart";sleep 3;done #this line checks for a running guake
while ! qdbus org.guake3.RemoteControl;do echo " >>>>> WARN:WaitingGuakeDBus";sleep 3;done #this line checks for a listening guake
function FUNCexecEcho() {
echo " EXEC: $@" >/dev/stderr
"$@"
};export -f FUNCexecEcho
function FUNCgrc() {
FUNCexecEcho qdbus org.guake3.RemoteControl /org/guake3/RemoteControl org.guake3.RemoteControl."$@"
}
# read parameters
acmd=()
astrIdList=()
astrOptList=()
iIdIndex=0
function FUNCchkCmd() { if [[ "${1:0:7}" == "-ID_CMD" ]];then return 0;else return 1;fi; } # <"$1">
while ! ${1+false};do
if FUNCchkCmd "${1}";then
echo " >>> NEW ID_CMD iIdIndex=$iIdIndex:"
astrOptList+=("${1#-ID_CMD}");shift
astrIdList+=("$1");shift;
continue;
fi
acmd+=("$1");shift
if ${1+false} || FUNCchkCmd "${1}";then
echo "astrOptList[$iIdIndex]='${astrOptList[$iIdIndex]}'"
echo "astrIdList[$iIdIndex]='${astrIdList[$iIdIndex]}'"
eval 'aIdCmd'${iIdIndex}'=("${acmd[@]}")';declare -p aIdCmd${iIdIndex}
((iIdIndex++))&&:
acmd=()
fi
done
declare -p astrIdList
# detect existing tabs
iTabCount="`FUNCgrc get_tab_count`"
iCurrentTabIndex="`FUNCgrc get_selected_tab`"
strCurrentTabUUID="`FUNCgrc get_selected_uuidtab`"
astrTabUUIDList=()
astrTabNameList=()
for((i=0;i<iTabCount;i++));do
echo
declare -p i
strTabName="`FUNCgrc get_tab_name $i`";declare -p strTabName
if((i==iCurrentTabIndex));then echo " CURRENT TAB";fi
FUNCgrc select_tab $i
astrTabUUIDList+=("`FUNCgrc get_selected_uuidtab`")
astrTabNameList+=("`FUNCgrc get_tab_name $i`")
done
FUNCgrc select_tab $iCurrentTabIndex # this first is reached fast so the user has not to wait a long time
: ${bGoBackToInitialTab:=false} #help will re-select select the tab this script was run on at the end
declare -p astrTabUUIDList |tr '[' '\n'
declare -p astrTabNameList |tr '[' '\n'
function FUNCrunCmd() {
strOpts="$1";shift
strTabName="$1";shift
strTabUUID="$1";shift
iIdCmd="$1";shift
aOptList=();if [[ -n "$strOpts" ]];then aOptList+=(`echo "$strOpts" |sed -r 's@(.)@\1 @g'`);fi
echo
echo " TabName: ${strTabName}, CMDOPTION(s): ${aOptList[@]} "
eval 'acmdRun=("${aIdCmd'${iIdCmd}'[@]}")';declare -p acmdRun
bSubShell=true
bForceCurrentTab=false
bRetryOnError=false
for strOpt in "${aOptList[@]}";do
case "$strOpt" in
n)bSubShell=false;; #help CMDOPTION: The default is to run using `bash -c '$cmd'`. To disable this, use like ex.: `-ID_CMDn cd ComePathToApplyAtCurrentShell`
c)bForceCurrentTab=true;if ! $bUsingXtermToRun;then echo " >>>>> WARNING <<<<< 'c' CMDOPTION is more reliable using '-x' option!!!";fi;; #help CMDOPTION: The tab name will only be ignored (but only if it does not exist ex.: "IgnoredCurrentTabName") and the current tab running this script will be used. This option is more reliable with -x option.
r)bRetryOnError=true;; #help CMDOPTION: if the command fails returning any error, it will retry running it after 3s.
*)$0 --help;echo "ERROR: invalid option '$strOpt' for strTabName='${strTabName}' and command: ${acmdRun[*]}";exit 1;;
esac
done
# create and run a tmp script
strFl="`tempfile`";chmod +x "$strFl"
echo '#!/bin/bash
cat $0; # review the command
'"$(declare -p acmdRun)"'; # '"${acmdRun[@]}"'
echo >'"${strFl}.started"'
if '$bRetryOnError';then
while ! "${acmdRun[@]}";do echo "failed error $?";sleep 3;done
else
"${acmdRun[@]}";
fi
' >"$strFl"
while true;do
bForceIgnoreStart=false
if $bUseBashAutoCmdMode && $bSubShell;then
bSubShell=false
echo "WARN: disabling subshell mode to let bUseBashAutoCmdMode work for now." >&2
fi
if $bSubShell;then
strCmd="bash -c ${strFl}"
else
# can the command passed thru qdbus param cause some problem if it is too complex? `bash -c` above is to prevent that.
strCmd="`declare -p acmdRun`;"'"${acmdRun[@]}"'
bForceIgnoreStart=true
fi
if $bUseBashAutoCmdMode;then
#echoc --alert "@{-n}execute_command_by_uuid was @nremoved@{-n}, therefore this script wont work that way anymore :(";
#exit 1
strExecFile="`bashAutoCmdOnStart.sh --getExecFileForUID "$strTabUUID"`"
echo "$strCmd" >>"$strExecFile"
while [[ -f "$strExecFile" ]];do
#echo "INFO: Waiting '$strExecFile' be consumed..."
read -p "(`date`)INFO: Waiting '$strExecFile' be consumed... skip waiting? (y/...)`echo -ne "\r"`" -t 1 -n 1 strResp&&:;if [[ "$strResp" == "y" ]];then break;fi
sleep 1
done
else
# this is for old guake version
if [[ "$strTabUUID" == "USE_CURRENT_TAB" ]];then
FUNCgrc execute_command "$strCmd"
else
FUNCgrc execute_command_by_uuid "$strTabUUID" "$strCmd"
fi
fi
sleep 1 #wait it start running
: ${bWaitStart:=true} #help wait the command start running before sending the next one
bForceRetry=false
bKeepTmpExecFile=false
bReallyWaitStart=$bWaitStart;if $bForceIgnoreStart;then bReallyWaitStart=false;fi
if $bReallyWaitStart;then
if $bForceCurrentTab || [[ "$strCurrentTabUUID" == "$strTabUUID" ]];then
echo " >>>>>>>>>>>> "
echo " >>>>> ATTENTION!!! this command '${acmdRun[*]}' was requested to be run on this current tab [$iCurrentTabIndex]'${strTabName}'($strCurrentTabUUID), so this script will not wait for the command to start and the related temporary exec file '${strFl}' will be kept."
echo " >>>>>>>>>>>> "
bKeepTmpExecFile=true
else
nW=0
while [[ ! -f "${strFl}.started" ]];do
echo " >>>>>>>>>>>> "
echo " > `date`: Waiting ($((nW++))) the command start running:"
echo " > TAB: strTabName='${strTabName}',strTabUUID='$strTabUUID'"
echo " > CMD$iIdCmd: '${acmdRun[*]}'"
echo " > It may fail if there was some command typed and not executed yet there."
echo " > It may fail if there happened an input request there."
echo " > So you better check if no problem happened!"
echo " > But if no problem happened and you force a retry, it will be buffered and will execute again."
echo " > Force retry run now? (y/...)"
echo " >>>>>>>>>>>> "
strResp="$(read -t 3 -n 1 strResp;echo "$strResp")";echo #the script was stopping here... why did I have to subshell?
if [[ "$strResp" == "y" ]];then echo " >>>>> Retrying";bForceRetry=true;break;fi
done
fi
fi
if ! $bForceRetry;then break;fi
done
: ${bRmTmpFiles:=false} #help delete temporary files
if $bRmTmpFiles && ! $bKeepTmpExecFile;then rm -v "${strFl}" "${strFl}.started";fi
};export -f FUNCrunCmd
# run the commands
for iId in "${!astrIdList[@]}";do
declare -p iId
echo " Id: ${astrIdList[iId]}"
bFound=false
for iTab in "${!astrTabNameList[@]}";do
strOpt="${astrOptList[iId]}"
bRunOnThisTab=false
if [[ "${astrTabNameList[iTab]}" == "${astrIdList[iId]}" ]];then bRunOnThisTab=true;fi
if ((iTab==iCurrentTabIndex)) && [[ "$strOpt" =~ .*c.* ]];then bRunOnThisTab=true;fi
if $bRunOnThisTab;then
FUNCrunCmd "$strOpt" "${astrIdList[iId]}" "${astrTabUUIDList[iTab]}" $iId
bFound=true
break
fi
done
: ${bAddTab:=true} #help if it doesnt exist yet
if ! $bFound;then
if $bAddTab;then
FUNCgrc add_tab "$HOME"
FUNCgrc rename_current_tab "${astrIdList[iId]}"
astrTabNameList+=("${astrIdList[iId]}")
astrTabUUIDList+=("`FUNCgrc get_selected_uuidtab`")
FUNCrunCmd "${astrOptList[iId]}" "${astrIdList[iId]}" "USE_CURRENT_TAB" $iId
else
echo " >>>>>>>>>>>> "
echo " >>>>> WARNING: could not find a matching tab name for '${astrIdList[iId]}'"
echo " >>>>>>>>>>>> "
fi
fi
done #for iId in "${!astrIdList[@]}";do
if $bGoBackToInitialTab;then FUNCgrc select_tab $iCurrentTabIndex;fi