V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
enchilada2020
V2EX  ›  Linux

想维护一套自己的 dotfiles 顺便练练 Shell 编程,有没有值得参考的仓库推荐一下

  •  
  •   enchilada2020 · 64 天前 · 2091 次点击
    这是一个创建于 64 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Linux 五年使用经验的骨灰级入门选手,之前都是现用现查,查完就忘,主打一个能干活就行。最近经常需要连到服务器上查各种日志和配置之类,但往往服务器默认的 Shell 环境太裸了,非常难用,所以痛下决心想把这块搞定。

    主要是想要能在主流 Linux 环境下快速配置,做到任何环境都有同样的命令行体验,不追求过度花里胡哨,保证最小可用性与生产力即可。

    因为要在保证体验统一的前提下尽量兼顾各种可能的情况,比如一些限制比较严格的生产环境之类的,遵循奥卡姆剃刀原则,如无必要勿增实体,所以优先选择那种主流服务器发行版都一定会带的工具,相比 Zsh 会选择 Bash ,相比 Emacs 会选择 Vim 等等。

    我知道有很多现成的优秀项目,比如 Oh My Zsh/starship ,但感觉这些大多是面向个人本地开发环境的,不适用于远程到生产环境的服务器做调查的场景。毕竟你总不可能为了查个日志在生产环境上搞了一大坨有的没的。

    简单看过几个 GithHub 上比较有名的个人 dotfiles 仓库,例如 holmanMathias的,一个是面向 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"
    }
    

    ...感觉 askask_for_confirmation 完全简化合并成一个函数的。

    21 条回复    2024-07-06 12:04:34 +08:00
    tpxcer
        1
    tpxcer  
       64 天前
    dotfiles 是个啥
    enchilada2020
        2
    enchilada2020  
    OP
       64 天前
    @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 仓库…
    mongoose
        3
    mongoose  
       64 天前   ❤️ 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 链接。
    noahlias
        4
    noahlias  
       64 天前
    既然最小可用了 不加任何东西 不应该是最 nerd 的吗
    纯文本不开任何高亮提示
    另外你说的这些 util 不都是 snippet 吗
    rick13
        5
    rick13  
       64 天前   ❤️ 1
    一步到位学 nix 。。
    valord577
        6
    valord577  
       64 天前
    1. 如果是配置 shell 的话 建议 alias 比如 alias ll='ls -alh' 其他的 .vimrc 等等
    2. 如果是面向服务器的话 可以用 docker 把要操作的目录-v 映射进来 使用 docker 配置好 shell 进行操作 (都自己管理服务器了 还不能装个 docker? [斜眼笑])
    noqwerty
        7
    noqwerty  
       64 天前 via iPhone   ❤️ 1
    只是为了多台机器同步配置环境的话可以看看 chezmoi
    tywtyw2002
        8
    tywtyw2002  
       64 天前   ❤️ 1
    其实大家都不会没事闲着去天天 refactor dotfiles 去。

    很多时候就是想到什么写什么进去,图的就是方便。

    现在有了 atuin ,无限 history 同步,更没有动力写 bash/zsh function 了。想找什么直接 ctrl+r 搜历史就行了。


    管理 dots ,我推荐用 chezmoi 。


    服务器上面的 dots ,要看是个人服务器还是生产的。安全原因,生产环境肯定不能装任何 dot ,至少我们是这么要求的。 日志简单的的 less/grep 搞定,复杂点 scp 拖回来 慢慢搞。
    Jeremial
        9
    Jeremial  
       64 天前   ❤️ 1
    要不看看我的, 主打一个够用就行.
    之前还加了各种判断环境, 可以自定义功能, 但是后面发现根本用的不到, 但是也没删掉.

    现在用的最多的就是 zsh 里面的 zimfw, 还有安装下 homebrew, neovim 啥的

    https://github.com/wyntau/dotfiles
    neroxps
        10
    neroxps  
       64 天前   ❤️ 1
    没人提 acme.sh
    enchilada2020
        11
    enchilada2020  
    OP
       64 天前 via Android
    @noahlias 你说的那种情况太极端了 最小可用不是啥也没有 就是因为裸的不满足可用趁手有生产力的状态才需要一套最基本的 dotfiles …至少基本的高亮 补全 清晰的 PS1 之类的要有 但需要额外安装的字体图标等等属于可有可无
    我在看他的代码时感觉不够优雅 想看看比较优秀的 shell 代码应该是什么样的
    0o0O0o0O0o
        12
    0o0O0o0O0o  
       64 天前   ❤️ 1
    优秀的 shell 代码可以看那些维护了几十年仍在活跃的包,或者 https://github.com/bminor/bash/tree/master/examples

    不过我不觉得为这个场景维护 dotfiles 是很常见或很明智的做法。
    agagega
        13
    agagega  
       64 天前 via iPhone
    觉得 shell 写起来兼容性差反人类的话,可以试试用 Python 写,反正现在几乎所有常见的类 Unix 环境都自带 Python
    blessingsi
        14
    blessingsi  
       64 天前
    #12 +1 ,这个场景真不太合适搞 dotfiles 。只是查个日志啥的就裸着用吧。。。
    enchilada2020
        15
    enchilada2020  
    OP
       64 天前
    @tywtyw2002
    @0o0O0o0O0o

    感觉使用姿势错了?我目前有需求的应用场景:
    1. 本地开发环境配置,包括新机器及各个项目下的 VS Code Dev Container 统一配置
    2. 服务器用户目录下的配置,保持与本地开发环境基本一致的使用体验

    因为是个人维护的 dotfiles ,清楚每一行代码都干了什么,所以就算在生产环境上用也不会有什么安全隐患…?同时也正是考虑到安全问题,不想用现成项目,以及那些需要额外安装的工具,因为不可控。
    经验不足,理解有误的地方请不吝赐教,感谢!
    enchilada2020
        16
    enchilada2020  
    OP
       64 天前
    @agagega 确实反人类,以前一直不喜欢就没碰,但感觉在*nix 世界只有 C 跟 Shell 是不可替代的。另外出于工作需要,有大量祖传 shell 要理解并根据需要修改,所以想着还是老老实实学一下好了。
    enchilada2020
        17
    enchilada2020  
    OP
       64 天前
    @blessingsi 那什么样的场景比较合适维护 dotfiles 呢?只是本地环境的话还是用现成项目就好了,方便省心又好看 hhh
    tengyufei
        18
    tengyufei  
       64 天前 via Android   ❤️ 2
    可以看看 ble.sh ,这个项目 作者堪称 bash 仙人
    tywtyw2002
        19
    tywtyw2002  
       64 天前   ❤️ 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
    }
    ```
    Davic1
        20
    Davic1  
       64 天前   ❤️ 1
    如果你需要同步 dotfiles ,推荐一篇文章 https://www.atlassian.com/git/tutorials/dotfiles

    我目前就是这么做的,https://github.com/0ptimista/dotfiles (主要用在 macOS 上)
    rayae
        21
    rayae  
       63 天前   ❤️ 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
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1189 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 23:56 · PVG 07:56 · LAX 16:56 · JFK 19:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.