Crontab could not create directory .ssh


最近在利用 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM