Linux 五年使用经验的骨灰级入门选手,之前都是现用现查,查完就忘,主打一个能干活就行。最近经常需要连到服务器上查各种日志和配置之类,但往往服务器默认的 Shell 环境太裸了,非常难用,所以痛下决心想把这块搞定。
主要是想要能在主流 Linux 环境下快速配置,做到任何环境都有同样的命令行体验,不追求过度花里胡哨,保证最小可用性与生产力即可。
因为要在保证体验统一的前提下尽量兼顾各种可能的情况,比如一些限制比较严格的生产环境之类的,遵循奥卡姆剃刀原则,如无必要勿增实体,所以优先选择那种主流服务器发行版都一定会带的工具,相比 Zsh 会选择 Bash ,相比 Emacs 会选择 Vim 等等。
我知道有很多现成的优秀项目,比如 Oh My Zsh/starship ,但感觉这些大多是面向个人本地开发环境的,不适用于远程到生产环境的服务器做调查的场景。毕竟你总不可能为了查个日志在生产环境上搞了一大坨有的没的。
简单看过几个 GithHub 上比较有名的个人 dotfiles 仓库,例如 holman 和 Mathias的,一个是面向 Mac ,一个用了 Zsh ,都不太理想。目前感觉 这个最合心意,但不太确定里面的写法是否符合最佳实践,比如其中的几个 util:
answer_is_yes() {
[[ "$REPLY" =~ ^[Yy]$ ]] \
&& return 0 \
|| return 1
}
ask() {
print_question "$1"
read -r
}
ask_for_confirmation() {
print_question "$1 (y/n) "
read -r -n 1
printf "\n"
}
...感觉 ask
跟 ask_for_confirmation
完全简化合并成一个函数的。
1
tpxcer 172 天前
dotfiles 是个啥
|
2
enchilada2020 OP @tpxcer
> “Dotfiles” are the funky little files in your *nix-based home directory that allow you to customize your nerdery: change how your prompt looks, set up your $PATH, adjust settings for Ruby’s IRB, completely change everything about Vim, and about a billion and a half other things. They’re fun. https://zachholman.com/2010/08/dotfiles-are-meant-to-be-forked/ 正文里的链接随便点进去一个都是 dotfiles 仓库… |
3
mongoose 172 天前 1
我自己 copy 了一些函数到我自己的 dotfiles 中
https://github.com/gruntwork-io/bash-commons https://github.com/ralish/bash-script-template https://github.com/hedzr/bash.sh 但是,具体的 dotfiles ,我没有具体收藏过链接。 事实上,如果只是为了维护自己的 dotfiles 的话,更多的是获取系统信息,更好的 log 格式化,字符串处理,反而是这种交互用的比较少吧。我用 stow 来链接我的 dotfiles ,win 下用 dploy 链接。 |
4
noahlias 172 天前
既然最小可用了 不加任何东西 不应该是最 nerd 的吗
纯文本不开任何高亮提示 另外你说的这些 util 不都是 snippet 吗 |
5
rick13 172 天前 1
一步到位学 nix 。。
|
6
valord577 172 天前
1. 如果是配置 shell 的话 建议 alias 比如 alias ll='ls -alh' 其他的 .vimrc 等等
2. 如果是面向服务器的话 可以用 docker 把要操作的目录-v 映射进来 使用 docker 配置好 shell 进行操作 (都自己管理服务器了 还不能装个 docker? [斜眼笑]) |
7
noqwerty 172 天前 via iPhone 1
只是为了多台机器同步配置环境的话可以看看 chezmoi
|
8
tywtyw2002 172 天前 1
其实大家都不会没事闲着去天天 refactor dotfiles 去。
很多时候就是想到什么写什么进去,图的就是方便。 现在有了 atuin ,无限 history 同步,更没有动力写 bash/zsh function 了。想找什么直接 ctrl+r 搜历史就行了。 管理 dots ,我推荐用 chezmoi 。 服务器上面的 dots ,要看是个人服务器还是生产的。安全原因,生产环境肯定不能装任何 dot ,至少我们是这么要求的。 日志简单的的 less/grep 搞定,复杂点 scp 拖回来 慢慢搞。 |
9
Jeremial 172 天前 1
要不看看我的, 主打一个够用就行.
之前还加了各种判断环境, 可以自定义功能, 但是后面发现根本用的不到, 但是也没删掉. 现在用的最多的就是 zsh 里面的 zimfw, 还有安装下 homebrew, neovim 啥的 https://github.com/wyntau/dotfiles |
11
enchilada2020 OP @noahlias 你说的那种情况太极端了 最小可用不是啥也没有 就是因为裸的不满足可用趁手有生产力的状态才需要一套最基本的 dotfiles …至少基本的高亮 补全 清晰的 PS1 之类的要有 但需要额外安装的字体图标等等属于可有可无
我在看他的代码时感觉不够优雅 想看看比较优秀的 shell 代码应该是什么样的 |
12
0o0O0o0O0o 172 天前 1
优秀的 shell 代码可以看那些维护了几十年仍在活跃的包,或者 https://github.com/bminor/bash/tree/master/examples
不过我不觉得为这个场景维护 dotfiles 是很常见或很明智的做法。 |
13
agagega 172 天前 via iPhone
觉得 shell 写起来兼容性差反人类的话,可以试试用 Python 写,反正现在几乎所有常见的类 Unix 环境都自带 Python
|
14
blessingsi 172 天前
#12 +1 ,这个场景真不太合适搞 dotfiles 。只是查个日志啥的就裸着用吧。。。
|
15
enchilada2020 OP @tywtyw2002
@0o0O0o0O0o 感觉使用姿势错了?我目前有需求的应用场景: 1. 本地开发环境配置,包括新机器及各个项目下的 VS Code Dev Container 统一配置 2. 服务器用户目录下的配置,保持与本地开发环境基本一致的使用体验 因为是个人维护的 dotfiles ,清楚每一行代码都干了什么,所以就算在生产环境上用也不会有什么安全隐患…?同时也正是考虑到安全问题,不想用现成项目,以及那些需要额外安装的工具,因为不可控。 经验不足,理解有误的地方请不吝赐教,感谢! |
16
enchilada2020 OP @agagega 确实反人类,以前一直不喜欢就没碰,但感觉在*nix 世界只有 C 跟 Shell 是不可替代的。另外出于工作需要,有大量祖传 shell 要理解并根据需要修改,所以想着还是老老实实学一下好了。
|
17
enchilada2020 OP @blessingsi 那什么样的场景比较合适维护 dotfiles 呢?只是本地环境的话还是用现成项目就好了,方便省心又好看 hhh
|
19
tywtyw2002 172 天前 1
@enchilada2020 #15
生产环境就是干干净净,除了业务相关的程序,其他的都不装啊。 业务程序也是遵守 devops 的 practice ,自动化 CI/CD 打包。 不用 k8s ,业务主机也是基于 IaC 的啊,Terraform 什么的。 99%的情况下,都不需要员工去 login 到生产环境里面,都是自动化部署了,除非升级,或者大错误导致系统级别的事故,才需要去登录。 如果是测试环境,那就跟私人电脑差不多,只要分配给你的资源你爱怎么折腾怎么折腾没人管。 1. 本地开发环境配置,包括新机器及各个项目下的 VS Code Dev Container 统一配置 这个只要同步 dot 文件就好了,如果机器类型不同那就用 chezmoi 去管理 2. 服务器用户目录下的配置,保持与本地开发环境基本一致的使用体验 一样,只要服务器让你搞,你就同步你的 dots 就好了。 可能是大家理解不同。 dots 一般来说不就是指代在*unix 下的配置文件吗。因为那些文件是 dot 开头的。。。 bash/zsh, dot 文件主要是配置 alias ,completion 之类的,还有一些你常用的命令缩写。 比如说这类的 ``` function cssh(){ ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $* } function fixssh() { if [[ -n $TMUX && -n $SSH_AUTH_SOCK ]]; then eval $(tmux show-env \ | sed -n 's/^\(SSH_[^=]*\)=\(.*\)/export \1="\2"/p') fi } ``` |
20
Davic1 172 天前 1
如果你需要同步 dotfiles ,推荐一篇文章 https://www.atlassian.com/git/tutorials/dotfiles
我目前就是这么做的,https://github.com/0ptimista/dotfiles (主要用在 macOS 上) |
21
rayae 171 天前 1
分享一下我的:
# If not running interactively, don't do anything [ -z "$PS1" ] && return MAIN_DEVICE=harvey if test -f $HOME/.config/.dotfiles_main_device; then MAIN_DEVICE=$HOSTNAME fi prompt_command() { local last_ret=$? history -a # terminal tab title local cwd="$PWD" local title="${cwd/#$HOME/\~}" if [ "$MAIN_DEVICE"x = "$HOSTNAME"x ] ; then echo -n -e "\\e]0;$title\\007" local HOST_FLAG="" else echo -n -e "\\e]0;$HOSTNAME > $title\\007" local HOST_FLAG="${COLOR_YELLOW}\h${COLOR_NOCOLOR} " fi export COLOR_NOCOLOR='\[\e[0m\]' export COLOR_RED='\[\e[0;31m\]' export COLOR_GREEN='\[\e[0;32m\]' export COLOR_ORANGE='\[\e[0;33m\]' export COLOR_BLUE='\[\e[0;34m\]' export COLOR_PURPLE='\[\e[0;35m\]' export COLOR_CYAN='\[\e[0;36m\]' export COLOR_WHITE='\[\e[0;37m\]' export COLOR_YELLOW='\[\e[0;33m\]' export COLOR_GRAY='\[\e[0;30m\]' export COLOR_LIGHT_WHITE='\[\e[1;37m\]' export COLOR_LIGHT_GRAY='\[\e[0;37m\]' export COLOR_LIGHT_RED='\[\e[1;31m\]' export COLOR_LIGHT_GREEN='\[\e[1;32m\]' export COLOR_LIGHT_BLUE='\[\e[1;34m\]' export COLOR_LIGHT_PURPLE='\[\e[1;35m\]' export COLOR_LIGHT_CYAN='\[\e[1;36m\]' export COLOR_LIGHT_YELLOW='\[\e[1;33m\]' export COLOR_LIGHT_GRAY='\[\e[1;30m\]' # PS1 case "$TERM" in xterm*|gnome*|konsole*|screen*) color_prompt=yes;; *) color_prompt=no;; esac if [ "$color_prompt" == no ]; then for name in $(env|grep ^COLOR_|cut -d= -f1);do unset ${name} done fi if [ $UID = 0 ] ; then local USER_FLAG="#" else local USER_FLAG="$" fi local SSH_IP=`echo $SSH_CLIENT | awk '{ print $1 }'` local SSH2_IP=`echo $SSH2_CLIENT | awk '{ print $1 }'` if [ $SSH2_IP ] || [ $SSH_IP ] ; then local HOST_FLAG="${COLOR_RESET}${COLOR_LIGHT_YELLOW}\h${COLOR_NOCOLOR} " fi if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then local DEBIAN_CHROOT=$(cat /etc/debian_chroot) fi local GIT_BRANCH='' if command -v git >/dev/null ; then local GIT_BRANCH='$(git branch 2> /dev/null | sed -e '/^[^*]/d' -e "s#* \(.*\)# ($(git config user.name) @ \1)#")' fi # last exit code PS1='' # chroot PS1="${PS1}${COLOR_RESET}${DEBIAN_CHROOT}" # show hostname if current not main device PS1="${PS1}${HOST_FLAG}" # current directory PS1="${PS1}${COLOR_LIGHT_GRAY}[${COLOR_LIGHT_GREEN}\w${COLOR_NOCOLOR}${COLOR_LIGHT_GRAY}]" # git repository info PS1="${PS1}${COLOR_PURPLE}${GIT_BRANCH}${COLOR_NOCOLOR}" # color by exit code if [ $last_ret == 0 ] ; then PS1="${PS1}${COLOR_LIGHT_WHITE} ${USER_FLAG}" else PS1="${PS1}${COLOR_LIGHT_RED} ($last_ret)${USER_FLAG}" fi # root/user flag PS1="${PS1}${COLOR_NOCOLOR} " export PS1 export PS2='> ' export PS3='#? ' export PS4='+' for name in $(env|grep ^COLOR_|cut -d= -f1);do unset ${name} done } export HISTFILESIZE=10000 export HISTSIZE=10000 export HISTCONTROL=erasedups:ignoredups:ignorespace # Don't put duplicate lines in the history and do not add lines that start with a space export HISTIGNORE="pwd:l:la:[bf]g:exit" # ignore such commands export HISTTIMEFORMAT='%Y%m%d-%H:%M:%S ' export PROMPT_COMMAND='prompt_command' export PROMPT_DIRTRIM=3 shopt -s cmdhist # combine multiline commands into single history shopt -s histappend # append history shopt -s checkwinsize # re-update LINEs and COLUMNs shopt -s autocd shopt -s extglob shopt -s dotglob shopt -s cdspell shopt -s dirspell shopt -s progcomp shopt -s no_empty_cmd_completion set -o noclobber stty -ixon # replace Ctrl-S for forward-search-history export EDITOR='vim' # Use bash-completion, if available 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 bind "set completion-ignore-case on" 2>/dev/null bind "set bell-style none" 2>/dev/null bind "set show-all-if-ambiguous on" 2>/dev/null bind "set show-all-if-unmodified on" 2>/dev/null # search history with arrow bind '"\e[A": history-search-backward' 2>/dev/null bind '"\e[B": history-search-forward' 2>/dev/null # alias alias egrep='egrep --color=auto' alias fgrep='fgrep --color=auto' alias grep='grep --color=auto' alias l='ls -CF' alias la='ls -A' alias ll='ls -alF' alias ls='ls --color=auto' alias ..="cd .." alias ...="cd ../.." alias ....="cd ../../.." alias cd..="cd .." if command -v dircolors > /dev/null 2>&1; then source <(dircolors) fi |