我想在共享服务器上设置一个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错误?
答案 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版本管理工具,例如chruby
或rvm
或rbenv
。 (我投票支持chruby btw)。所有这些文档非常密集。如果您最终有一个或多个问题,作者在解决问题方面非常有帮助。
答案 2 :(得分:0)
...我只是在犯一些菜鸟PATH错误吗?
是的,我想是这样...我不确定您为什么要分配GEM_PATH
,而我并不需要这样做,并认为您也许想要GEM_HOME
。尽管此后情况可能有所变化,但当前的现在将会在此处发布。
## Ruby exports for user level gem & bundle installs
export GEM_HOME="${HOME}/.gem"
export PATH="${GEM_HOME}/bin:${PATH}"
...到要向服务器进行身份验证的每个用户的~/.bash_aliases
之类的地方。
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
使用文档获取详细参考