Crontab could not create directory .ssh

最近在利用 crontab 構建自動備份時,遇到了一個問題。個人腳本中包含了用於服務器用戶切換使用的 ssh 命令。當我登陸到服務器上時,腳本執行正常;當我沒有登陸到服務器上時,腳本執行失敗,錯誤提示是:html

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

 

在登陸到服務器上後,能夠看到 「/home/server/.ssh」 路徑是存在的,也是正常的。node

各個用戶間的 ssh key 也已經生成好了,在登陸到服務器上後,手動調用主腳本,能夠正常的完成腳本的執行流程,可是由 crontab 自動調用時,仍然沒法正常工做。git

在網上查找相關信息的時候,在 stackoverflow 上有人問相似的問題,可是並無人給出了可行的解答。 rsync code will run, but not in cron. 原文連接shell

資料查找沒有找到可行的結果,只能本身想辦法了。由於登陸和不登陸結果不同,首先懷疑是否是登陸致使環境變量有所改變。爲了確認這一點,我在主腳本中加入了 echo 命令,來打印 SSH 使用到的環境變量。具體的環境變量包含如下內容:vim

     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’」bash

這個問題仍是很奇怪,不知道爲何會這樣。爲了去解決這個問題,我嘗試在本地部署一個自動執行腳本,用於自動登陸到服務器上調用服務器自動備份腳本,來實現自動備份。當自動登陸部署完成後,發現了一個新的問題:當我登陸在服務器上時,自動登陸能夠執行成功;當我沒有登陸到服務器上時,自動登陸沒法執行成功。在沒有登陸上服務器時,用戶目錄和登陸上以後不同??服務器

爲了驗證這個想法,執行一下 mount 命令,結果以下:cookie

/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 命令。對比發現,在自動執行時,用戶目錄是沒有被掛載的。那麼,這就是問題緣由了:session

在沒有登陸到服務器上時,用戶目錄沒有被掛載。由於沒有被掛載,因此用戶目錄的權限不對!!dom

爲了驗證這個想法,再次登陸到服務器上,手動將用戶目錄進行卸載

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

相關文章
相關標籤/搜索