最近在利用 crontab 构建自动备份时,遇到了一个问题。我的脚本中包含了用于服务器用户切换使用的 ssh 命令。当我登录到服务器上时,脚本执行正常;当我没有登录到服务器上时,脚本执行失败,错误提示是:

Could not create directory '/home/server/.ssh'

在登录到服务器上后,可以看到 “/home/server/.ssh” 路径是存在的,也是正常的。

各个用户间的 ssh key 也已经生成好了,在登录到服务器上后,手动调用主脚本,可以正常的完成脚本的执行流程,但是由 crontab 自动调用时,仍然无法正常工作。

在网上查找相关信息的时候,在 stackoverflow 上有人问类似的问题,但是并没有人给出了可行的解答。 rsync code will run, but not in cron. 原文链接

资料查找没有找到可行的结果,只能自己想办法了。因为登录和不登录结果不一样,首先怀疑是不是登录导致环境变量有所改变。为了确认这一点,我在主脚本中加入了 echo 命令,来打印 SSH 使用到的环境变量。具体的环境变量包含以下内容:

     DISPLAY               The DISPLAY variable indicates the location of the X11 server.  It is automatically set by ssh to point to a value of the form
``hostname:n'', where ``hostname'' indicates the host where the shell runs, and `n' is an integer >= 1. ssh uses this special value to
forward X11 connections over the secure channel. The user should normally not set DISPLAY explicitly, as that will render the X11 con-
nection insecure (and will require the user to manually copy any required authorization cookies). HOME Set to the path of the user's home directory. LOGNAME Synonym for USER; set for compatibility with systems that use this variable. MAIL Set to the path of the user's mailbox. PATH Set to the default PATH, as specified when compiling ssh. SSH_ASKPASS If ssh needs a passphrase, it will read the passphrase from the current terminal if it was run from a terminal. If ssh does not have a
terminal associated with it but DISPLAY and SSH_ASKPASS are set, it will execute the program specified by SSH_ASKPASS and open an X11
window to read the passphrase. This is particularly useful when calling ssh from a .xsession or related script. (Note that on some
machines it may be necessary to redirect the input from /dev/null to make this work.) SSH_AUTH_SOCK Identifies the path of a UNIX-domain socket used to communicate with the agent. SSH_CONNECTION Identifies the client and server ends of the connection. The variable contains four space-separated values: client IP address, client
port number, server IP address, and server port number. SSH_ORIGINAL_COMMAND This variable contains the original command line if a forced command is executed. It can be used to extract the original arguments. SSH_TTY This is set to the name of the tty (path to the device) associated with the current shell or command. If the current session has no
tty, this variable is not set. TZ This variable is set to indicate the present time zone if it was set when the daemon was started (i.e. the daemon passes the value on
to new connections). USER Set to the name of the user logging in.

通过打印上述环境变量,发现登录前和登录后打印出的结果完全一致,但是没有登录的话,自动执行脚本就会提示“Could not create directory ‘/home/server/.ssh’”

这个问题还是很奇怪,不知道为什么会这样。为了去解决这个问题,我尝试在本地部署一个自动执行脚本,用于自动登录到服务器上调用服务器自动备份脚本,来实现自动备份。当自动登录部署完成后,发现了一个新的问题:当我登录在服务器上时,自动登录可以执行成功;当我没有登录到服务器上时,自动登录无法执行成功。在没有登录上服务器时,用户目录和登录上之后不一样??

为了验证这个想法,执行一下 mount 命令,结果如下:

/dev/sda1 on / type ext4 (rw,errors=remount-ro)
proc on /proc type proc (rw,noexec,nosuid,nodev)
sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
none on /sys/fs/cgroup type tmpfs (rw)
none on /sys/fs/fuse/connections type fusectl (rw)
none on /sys/kernel/debug type debugfs (rw)
none on /sys/kernel/security type securityfs (rw)
udev on /dev type devtmpfs (rw,mode=0755)
devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)
tmpfs on /run type tmpfs (rw,noexec,nosuid,size=10%,mode=0755)
none on /run/lock type tmpfs (rw,noexec,nosuid,nodev,size=5242880)
none on /run/shm type tmpfs (rw,nosuid,nodev)
none on /run/user type tmpfs (rw,noexec,nosuid,nodev,size=104857600,mode=0755)
none on /sys/fs/pstore type pstore (rw)
systemd on /sys/fs/cgroup/systemd type cgroup (rw,noexec,nosuid,nodev,none,name=systemd)
/home/server/.Private on /home/server type ecryptfs (ecryptfs_check_dev_ruid,ecryptfs_cipher=aes,ecryptfs_key_bytes=16,ecryptfs_unlink_sigs,ecryptfs_sig=a1f33ec3321f0ef9,ecryptfs_fnek_sig=705c22000a171cfe)

从 mount 的结果上看,用户目录是被 mount 上的。再次进行测试,在 crontab 里通过自动脚本执行 mount 命令。对比发现,在自动执行时,用户目录是没有被挂载的。那么,这就是问题原因了:

在没有登录到服务器上时,用户目录没有被挂载。因为没有被挂载,所以用户目录的权限不对!!

为了验证这个想法,再次登录到服务器上,手动将用户目录进行卸载

sudo umount /home/server

卸载掉用户目录后,再次进入目录中进行查看

server@gitlabserver:~$ ls -a
. .. Access-Your-Private-Data.desktop
.bash_history .ecryptfs .kde
.Private README.txt .viminfo

我们发现,用户目录到内容变了。

因为服务器用户目录是经过了 “ecryptfs” 加密,所以在没有登录和登录后不一样。知道了这一点,解决自动登录到方法也就变得简单了:将用户目录中的 .ssh 目录拷贝到卸载后的用户目录中。

经过上述的拷贝,自动执行的脚本终于可以顺利执行了,问题圆满解决。

我在 stackoverflow 上回答了这个问题。自己记录一下,看看是不是能帮到别人: stackoverflow

欢迎转载,转载请保留: 
转自Elta 的博客:http://www.eltaera.com//2017/01/18/crontab_ssh.html

Crontab could not create directory .ssh的更多相关文章

  1. cygwin Could not create directory '/home/Administrator/.ssh'

    在cygwin下运行: ssh-keygen -C "634772208@qq.com" -t rsa 时,出现如下错误: cygwin Could not create dire ...

  2. org.apache.hadoop.hdfs.server.namenode.SafeModeException: Cannot create directory /user/hive/warehouse/page_view. Name node is in safe mode

    FAILED: Error in metadata: MetaException(message:Got exception: org.apache.hadoop.ipc.RemoteExceptio ...

  3. vsftp关于"550 create directory operation failed"问题解决

    前提: 昨天晚上配置好了vsftp, 但登陆后,除了浏览,什么也干不了.(如新建文件/文件夹, 删除文件, 重命名等都不可操作) 都是弹出 "550 create directory ope ...

  4. [hadoop]Cannot create directory /mdrill/tablelist/fact_seller_all_d. Name node is in safe mode.

    在执行mdrill创建表的时候报如下异常(蓝色部分为关键): [mdrill@hadoop1101 bin]$ ./bluewhale mdrill create ./create.sql higo ...

  5. 550 Create directory operation failed

    往Linux系统中上传文件时候,我们经常会使用FTP连接Linux,也经常会使用mkdir命令来创建目录.最近发现用mkdir创建目录时提示550 Create directory operation ...

  6. Linux虚拟主机通过FTP软件创建目录时提示550 Create Directory Operation Failed

    更新时间:2017-06-07 13:26:11   分享: 问题描述 通过FTP软件连接Linux虚拟主机,在尝试创建新目录时,服务器返回错误提示:550 Create Directory Oper ...

  7. 非root用户启动redis容器报错mkdir: cannot create directory '/bitnami/redis': Permission denied

    问题:使用docker启动容器时,报错如下 zh@debian:~/testPath$ docker-compose up redis Starting testpath_redis_1 ... do ...

  8. HTTP Status 500 - Unable to create directory

    分析原因: 例如:java web项目 上传图片创建文件夹cd /data/apps/static-web/sjk/driver/attachment/编号/文件名称.jpg 在创建文件目录 /dat ...

  9. Hadoop "Cannot create directory .Name node is in safe mode."解决方案

    转载自:http://www.waitig.com/hadoop-name-node-is-in-safe-mode.html 在使用Hadoop建立文件的时候,出现“Cannot create di ...

随机推荐

  1. Sublime Text 3 搭建 Golang 开发环境

    安装Golang go语言主页: https://golang.org/ go语言安装下载: https://golang.org/dl 环境变量设置: GOROOT: GOROOT变量设置go安装的 ...

  2. mac home/end/pageup/pageDown

    home:按fn+左键 end:按fn+右键 pageup:按fn+上键 pagedown:按fn+下键

  3. Is it possible to run native sql with entity framework?

    For .NET Framework version 4 and above: use ObjectContext.ExecuteStoreCommand() if your query return ...

  4. angularJS 系列(二)——理解指令 understanding directives

    参考:https://github.com/angular/angular.js/wiki/Understanding-Directives Injecting, Compiling, and Lin ...

  5. Content Provider 小结

    Android中的四大组件之一ContentProvider,它支持多个应用间进行存储和读取数据等操作,实现不同应用间的数据共享. ContentProvider,解释为内容提供商.顾名思义,就是对外 ...

  6. JSON的BUG

    问题描述: method_cfg["input_method"][0].asString() 报错误: test1.cpp:40:46: error: ambiguous over ...

  7. iOS所有常用证书,appID,Provisioning Profiles配置说明及制作图文教程

    概述: 苹果的证书繁锁复杂,制作管理相当麻烦,今天决定重置一个游戏项目中的所有证书,做了这么多次还是感觉很纠结,索性直接记录下来,日后你我他查阅都方便: 首先得描述一下各个证书的定位,作用,这样在制作 ...

  8. iOS开发——汉字转拼音

    以前有一次做一个天气预报的项目,有一个功能是输入城市名,请求该城市的天气,需要把汉字转化成拼音,比如深圳——>shenzhen,加入到参数中.当时在网上找了一下,网友给出的方法很多都用不了,现在 ...

  9. STM32 驱动1602液晶

    利用STM32f103c8t6单片机驱动1602A液晶进行显示功能 上图即为写入信息后的效果图 本人用的是STM32的核心系统,无任何外设 库函数:3.5版本的库函数 驱动模式:采用4线驱动模式 供电 ...

  10. javascript--study

    1.函数传参:按值传递 对于数字.字符串等是将它们的值传递给了函数参数,函数参数的改变不会影响函数外部的变量. 对于数组和对象等是将对象(数组)的变量的值传递给了函数参数,这个变量保存的指向对象(数组 ...