没有root安装Jekyll

时间:2013-12-11 23:12:33

标签: ruby path rubygems gem jekyll

我想在共享服务器上设置一个jekyll博客。当我尝试安装Jekyll时,我得到“你没有写权限”。如何在没有root或sudo的情况下修复此问题?

更多细节:

我在共享服务器上有空间并且没有root访问权限。虽然托管公司根据我的要求安装了Ruby,但我无法安装Ruby。

当我尝试安装Jekyll时,我使用

user@hosting.org [~]# gem install jekyll

这是我得到的回应:

ERROR:  While executing gem ... (Gem::FilePermissionError)
You don't have write permissions into the /usr/lib/ruby/gems/1.8 directory.

我已经看到了改变我尝试过的GEMPATH的不同建议,包括

export GEM_PATH=/home/user/something

但即便这样做了

gem env 

仍然会导致

GEM PATHS:
- /usr/lib/ruby/gems/1.8
- /home/user/.gem/ruby/1.8

任何提示?是否可以在没有root或sudo priviliges的情况下安装jekyll,或者我只是制作了一些新手PATH错误?

4 个答案:

答案 0 :(得分:10)

我暂时没有找到答案。在#jekyll IRC上,用户指着我the Arch wiki,我发现事情是强制安装为单个用户:

gem install jekyll --user-install

答案 1 :(得分:0)

原因是Mac附带的默认Ruby(我假设这样,但对于某些Linux发行版也是如此)将gem安装到需要修改内容权限的用户文件夹。确切地说,这不是Ruby错误。

也就是说,自Ruby 1.8.7 is not supported any more起,您最好避免使用它并使用其中一种备用ruby版本管理工具,例如chrubyrvmrbenv 。 (我投票支持chruby btw)。所有这些文档非常密集。如果您最终有一个或多个问题,作者在解决问题方面非常有帮助。

答案 2 :(得分:0)

  
    

...我只是在犯一些菜鸟PATH错误吗?

  

是的,我想是这样...我不确定您为什么要分配GEM_PATH,而我并不需要这样做,并认为您也许想要GEM_HOME。尽管此后情况可能有所变化,但当前的现在将会在此处发布。

TLDR

  1. 我通常会写一些诸如...
## Ruby exports for user level gem & bundle installs
export GEM_HOME="${HOME}/.gem"
export PATH="${GEM_HOME}/bin:${PATH}"

...到要向服务器进行身份验证的每个用户的~/.bash_aliases之类的地方。

  1. 然后在任何git-shell-commands脚本中,对于使用Gems的经过身份验证的用户,请source先进行上述设置。

  
    

我想在共享服务器上建立一个jekyll博客。当我尝试安装Jekyll时,出现“您没有写权限”。如何在没有root或sudo的情况下解决此问题?

  

也许值得一试published前一段时间的项目。如果您愿意>= 4进行PR,请在具有Bash版本Mac的Linux系统上进行编写和测试。否则,对于共享服务器,坚持使用Xenial,Ubuntu或最新鲜 Raspberry风格的Debian可能引起的麻烦最少。

这里有一些片段可以帮助您自动回答问题...

/usr/local/etc/Jekyll_Admin/shared_functions/user_mods/ jekyll_gem_bash_aliases.sh

#!/usr/bin/env bash


jekyll_gem_bash_aliases(){    ## jekyll_gem_bash_aliases <user>
    local _user="${1:?No user name provided}"
    local _home="$(awk -F':' -v _user="${_user}" '$0 ~ "^" _user ":" {print $6}' /etc/passwd)"
    if [ -f "${_home}/.bash_aliases" ]; then
        printf '%s/.bash_aliases already exists\n' "${_home}" >&2
        return 1
    fi

    ## Save new user path variable for Ruby executables
    su --shell "$(which bash)" --command 'touch ${HOME}/.bash_aliases' --login "${_user}"
    tee -a "${_home}/.bash_aliases" 1>/dev/null <<'EOF'
## Ruby exports for user level gem & bundle installs
export GEM_HOME="${HOME}/.gem"
export PATH="${GEM_HOME}/bin:${PATH}"
EOF
    su --shell "$(which bash)" --command 'chmod u+x ${HOME}/.bash_aliases' --login "${_user}"

    printf '## %s finished\n' "${FUNCNAME[0]}"
}

以上内容被三个使用sudo级权限(特别是jekyll_usermod.sh)的脚本之一使用...但是不要被所有的扭曲所困扰我要问的是Bash,因为上述函数 story moral 是这样写的...

## Ruby exports for user level gem & bundle installs
export GEM_HOME="${HOME}/.gem"
export PATH="${GEM_HOME}/bin:${PATH}"

...到类似/srv/bill/.bash_aliases的地方,它将在source脚本和/或其他共享帐户设置的共享功能中获得 git-shell-commands d ...

/usr/local/etc/Jekyll_Admin/shared_functions/user_mods/ jekyll_user_install.sh

#!/usr/bin/env bash


jekyll_user_install(){    ## jekyll_user_install <user>
    local _user="${1:?No user name provided}"
    su --shell "$(which bash)" --login "${_user}" <<'EOF'
source "${HOME}/.bash_aliases"

mkdir -vp "${HOME}"/{git,www}
## Initialize Jekyll repo for user account
_old_PWD="${PWD}"
mkdir -vp "${HOME}/git/${USER}"
cd "${HOME}/git/${USER}"
git init .
git checkout -b gh-pages

_ruby_version="$(ruby --version)"
printf 'Ruby Version: %s\n' "${_ruby_version}"
_ruby_version="$(awk '{print $2}' <<<"${_ruby_version%.*}")"
_ruby_version_main="${_ruby_version%.*}"
_ruby_version_sub="${_ruby_version#*.}"
if [[ "${_ruby_version_main}" -ge '2' ]] && [[ "${_ruby_version_sub}" -ge '1' ]]; then
    gem install bundler -v '< 2'
    gem install jekyll -v '3.8.5'

    bundle init
    bundle install --path "${HOME}/.bundle/install"
    bundle add jekyll-github-metadata github-pages

    bundle exec jekyll new --force --skip-bundle "${HOME}/git/${USER}"
    bundle install
else
    echo 'Please see to installing Ruby verion >= 2.4' >&2
    echo 'Hints may be found at, https://jekyllrb.com/docs/installation/' >&2
fi

git config receive.denyCurrentBranch updateInstead

cat >> "${HOME}/git/${USER}/.gitignore" <<EOL
# Ignore files and folders generated by Bundler
Bundler
vendor
.bundle
Gemfile.lock
EOL

git add --all
git -c user.name="${USER}" -c user.email="${USER}@${HOSTNAME}" commit -m "Added files from Bundler & Jekyll to git tracking"
cd "${_old_PWD}"
EOF
    local _exit_status="${?}"

    printf '## %s finished\n' "${FUNCNAME[0]}"
    return "${_exit_status}"
}
  

注意,.bash_aliases就文件命名而言是任意的,只要是一致的,甚至可以通过 .gems_aliases 之类的方式更明确地指出;最终用户不需要知道幕后发生了什么 来使神奇发生。

...希望可以显示出一种清晰的方法,使 gem install someThing 和相关命令首先搜索用户已安装的软件包。虽然万一需要另一个例子...

~/git-shell-commands/ jekyll-init

#!/usr/bin/env bash

__SOURCE__="${BASH_SOURCE[0]}"
while [[ -h "${__SOURCE__}" ]]; do
    __SOURCE__="$(find "${__SOURCE__}" -type l -ls | sed -n 's@^.* -> \(.*\)@\1@p')"
done
__DIR__="$(cd -P "$(dirname "${__SOURCE__}")" && pwd)"
__NAME__="${__SOURCE__##*/}"
__AUTHOR__='S0AndS0'
__DESCRIPTION__='Initializes new Git repository with a gh-pages branch'


## Provides 'failure'
# source "${__DIR__}/shared_functions/failure"
# trap 'failure "LINENO" "BASH_LINENO" "${BASH_COMMAND}" "${?}"' ERR

## Provides: argument_parser <arg-array-reference> <acceptable-arg-reference>
source "${__DIR__}/shared_functions/arg_parser"

## Provides: git_add_commit <string>
source "${__DIR__}/shared_functions/git_shortcuts"

## Provides: __license__ <description> <author>
source "${__DIR__}/shared_functions/license"


usage(){
    _message="${1}"
    _repo_name="${_repo_name:-repository-name}"
    cat <<EOF
## Usage
# ssh ${USER}@host-or-ip ${__NAME__} ${_git_args[@]:-$_repo_name}
#
# ${__DESCRIPTION__}
#
# --quite
#  Git initializes quietly
#
# --shared
#  Allow git push for group $(groups | awk '{print $1}')
#
# --template=<path>
#  Template git repository that git init should pull from
#
# ${_repo_name}
#  Name of repository to internalize or add Jekyll gh-pages branch to
#
## For detailed documentation of the above options.
##  See: git help init
#
# --clean
#  Remove non-git related files and directories from gh-pages branch prior to
#  initializing Jekyll related files. This allows for files from previous branch
#  to remain separate from files being tracked on the gh-pages branch.
#
# -l --license
# Shows script or project license then exits
#
# -h    --help help
#  Displays this message and exits
#
## The following options maybe used to modify the generated _config.yml file
#
# --title ${_title}
# --email ${_email}
# --twitter-username ${_twitter_username}
# --github-username ${_github_username}
EOF
    if [ -n "${_message}" ] && [[ "${_message}" != '0' ]]; then
        printf 'Error - %s\n' "${_message}" >&2
    fi
}


_args=("${@:?# No arguments provided try: ${__NAME__} help}")
_valid_args=('--help|-h|help:bool'
             '--license|-l|license:bool'
             '--quiet:bool'
             '--clean:bool'
             '--shared:bool'
             '--template:path'
             '--title:print'
             '--email:print'
             '--twitter-username:posix'
             '--github-username:posix'
             '--repo-name:posix-nil')
argument_parser '_args' '_valid_args'
_exit_status="$?"
_git_args=()
if ((_quiet)); then  _git_args+=('--quiet');  fi
if ((_shared)); then _git_args+=('--shared'); fi
if [ -n "${_template}" ]; then  _git_args+=("--template='${_template}'"); fi
if [ -n "${_repo_name}" ]; then _git_args+=("${_repo_name}"); fi


## Set defaults for some variables if not already set
_github_username="${_github_username:-$USER}"
if [ -z "${_title}" ]; then
    for _word in ${_repo_name//[-_]/ }; do
        if [[ "${#_word}" -ge '4' ]]; then
            _temp_title+=("${_word^}")
        else
            _temp_title+=("${_word}")
        fi
    done
    _title="${_temp_title[@]}"
fi
_bundle_path="${HOME}/.bundle/install"


if ((_help)) || ((_exit_status)); then
    usage "${_exit_status}"
    exit "${_exit_status}"
elif ((_license)); then
    __license__ "${__DESCRIPTION__}" "${__AUTHOR__}"
    exit 0
fi

if [ -z "${_repo_name}" ]; then
    usage 'missing repository name argument!'
    exit "1"
fi

_git_path="${HOME}/git/${_repo_name:?No repository name provided}"
_old_PWD="${PWD}"
if [ -d "${_git_path}" ]; then cd "${_git_path}"; fi
_git_dir="$(git rev-parse --git-dir 2>/dev/null)"


if [[ "${_git_path}/${_git_dir}" == "${_git_path}/.git" ]]; then
    printf '# Skipping git init, path already tracked by git: %s\n' "${_git_preexisting_dir}"
elif [[ "${_git_path}/${_git_dir}" == "${_git_path}/." ]]; then
    echo '# Bare git repository detected, cannot install Jekyll to that right now'
    exit 1
else
    if [ -e "${HOME}/git-shell-commands/git-init" ]; then
        "${HOME}/git-shell-commands/git-init" ${_git_args[@]}
    else
        cd "${HOME}/git" || exit 1
        git init ${_git_args[@]}
    fi
fi


cd "${_git_path}" || exit 1
_git_branches="$(git branch --list)"
_orig_branch="$(awk '/\*/{print $2}' <<<"${_git_branches}")"
_pages_branch="$(awk '/gh-pages/{print $2}' <<<"${_git_branches}")"
if [ -n "${_pages_branch}" ]; then
    printf '# There is already a pages branch %s for repository %s\n' "${_pages_branch}" "${_repo_name}"
    exit 1
fi

git_add_commit "Added files on ${_orig_branch} prior to installing Bundler & Jekyll to gh-pages branch"

git checkout -b gh-pages
if [[ "$(git config receive.denyCurrentBranch)" != 'updateInstead' ]]; then
    git config receive.denyCurrentBranch updateInstead
fi

if ((_clean)); then
    for _path in ${_git_path}/*; do
        case "${_path}" in
            *'.git')       [[ -d "${_path}" ]] && continue ;;
            *'.gitignore') [[ -f "${_path}" ]] && continue ;;
        esac
        git rm -rf "${_path}"
    done
    git_add_commit 'Cleaned gh-pages branch of files from parent branch'
fi


modify_config_yml(){
    if ! [ -f "${_git_path}/_config.yml" ]; then
        printf 'Error - no Jekyll config file found under %s\n' "${_git_path}" >&2
        return 1
    fi

    if [ -n "${_title}" ]; then
        sed -i "/title:/ { s#:[a-zA-Z 0-9]*#: ${_title}#; }" "${_git_path}/_config.yml"
    fi
    if [ -n "${_email}" ]; then
        sed -i "/email:/ { s#:[a-zA-Z 0-9]*#: ${_email}#; }" "${_git_path}/_config.yml"
    fi
    if [ -n "${_twitter_username}" ]; then
        sed -i "/_twitter_username:/ { s#:[a-zA-Z 0-9]*#: ${_twitter_username}#; }" "${_git_path}/_config.yml"
    fi
    if [ -n "${_github_username}" ]; then
        sed -i "/github_username:/ { s#:[a-zA-Z 0-9]*#: ${_github_username}#; }" "${_git_path}/_config.yml"
    fi

    if [[ "${_repo_name}" != "${_github_username}" ]]; then
        tee -a "${_git_path}/_config_baseurl.yml" 1>/dev/null <<EOF
# Use base URL to simulate GitHub pages behaviour
baseurl: "${_repo_name}"
EOF
    fi
}


source "${HOME}/.bash_aliases"
bundle init || exit "${?}"
bundle install --path "${_bundle_path}"
bundle add jekyll
bundle exec jekyll new --force --skip-bundle "${_git_path}"
modify_config_yml
bundle install


cat >> "${_git_path}/.gitignore" <<EOF
# Ignore files and folders generated by Bundler
Bundler
vendor
.bundle
Gemfile.lock
EOF

git_add_commit 'Added files from Bundler & Jekyll to git tracking'

[[ "${_old_PWD}" == "${_git_path}" ]] || cd "${_old_PWD}"


printf '# Clone %s via: git clone %s@domain_or_ip:%s\n' "${_repo_name}" "${USER}" "${_git_path//${HOME}\//}"
printf '# %s finished\n' "${__NAME__}"

...还显示了如何 bundle install someThing 到某个地方。

祝您好运,并发表评论,如果您被卡住。

答案 3 :(得分:0)

这在MAC中对我有用

1。将宝石放置在用户的主文件夹中。在.bashrc或.zshrc中添加以下命令

export GEM_HOME=$HOME/gems
export PATH=$HOME/gems/bin:$PATH

2。使用安装命令

gem install jekyll bundler

3。验证安装

 jekyll -v

使用文档获取详细参考

https://jekyllrb.com/docs/troubleshooting/#no-sudo