เรียกใช้งานคำสั่ง rsync ผ่าน ssh ด้วยเอเจนต์ ssh ผ่าน crontab


18

ฉันมี cronjob:

0 9 * * * rsync -a mydir remote_machine:

ฉันติดตั้งสิ่งนี้ด้วย 'crontab -e' ฉันมี ssh-agent กำลังทำงานอยู่และเมื่อฉันรันคำสั่ง rsync มันทำงานโดยไม่มีการโต้ตอบกับผู้ใช้หรือการป้อนรหัสผ่านใด ๆ แต่ cronjob ล้มเหลวด้วยข้อความต่อไปนี้:

Date: Wed,  9 Dec 2009 11:11:00 -0600 (CST)
From: Cron Daemon <me@my_machine.my_domain>
To: me@my_machine.my_domain
Subject: Cron <me@my_machine> rsync -a /home/me/mydir remote_machine:

Permission denied, please try again.
Permission denied, please try again.
Permission denied (publickey,gssapi-with-mic,password).
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at /SourceCache/rsync/rsync-35.2/rsync/io.c(452)
[sender=2.6.9]

ทำไมมันใช้ไม่ได้ ฉันรู้ว่า cronjobs ทำงานด้วยฉันเป็นผู้ใช้ (ถ้าฉันเรียกใช้ '* * * * * สัมผัส / tmp / a' ฉันเป็นเจ้าของไฟล์) ดังนั้นฉันคิดว่า rsync กำลังเข้าสู่ระบบในขณะที่ฉันใช้กุญแจส่วนตัวของฉัน ...

คำตอบ:


10

เชลล์เซสชัน cron ของคุณไม่มีความรู้เกี่ยวกับเอเจนต์ ssh ดังนั้นจึงไม่สามารถคุยกับมันได้

เมื่อตัวแทนเริ่มต้นคุณสามารถใส่ข้อมูลที่จำเป็นสำหรับตัวแทนบางแห่งสำหรับเซสชัน cron เพื่อรับ

ตัวอย่าง:

AGENT="ssh-agent -s"
if [ ! -d $HOME/.ssh/agent ]; then
        mkdir -p $HOME/.ssh/agent
fi
#
# Start an agent if there isn't one running already.
#
pid=`ps -u$LOGNAME | grep ssh-age | awk '{print $1}'`
if [ -z "$pid" ]; then
        $AGENT | grep -v echo > $HOME/.ssh/agent/$HOST & pid=$!
        sleep 1 # Let it fork and stuff
fi

จากนั้นเพิ่มกุญแจของคุณไปยังตัวแทน

ssh-add $HOME/.ssh/id_dsa

ตอนนี้งาน cron ของคุณควรทำสิ่งนี้ก่อนที่จะพยายามใช้ ssh:

#
# Get our parent to pick up the required SSH env vars.
#
. $HOME/.ssh/agent/$HOST

... หลังจากนั้นเซสชัน ssh ควรดำเนินการตามปกติ


ดังนั้นฉันจะใส่ทุกสิ่งตัวแทนในสคริปต์ตามด้วยคำสั่ง rsync หรือฉันสามารถวางไว้ในไฟล์. profile หรือ. bashrc ที่ cron โหลดโดยอัตโนมัติเมื่อมันเริ่มเชลล์สำหรับ cronjob หรือไม่
aaron

ฉันจะใส่ข้อมูลตัวแทนในสคริปต์ที่รันคำสั่ง rsync
David Mackintosh

3
ทั้งหมดที่ฉันต้องการคือการจัดหาตัวแปร env SSH_AUTH_SOCK และ SSH_AGENT_PID (ฉันใส่ไว้ใน. ssh-agent แทนที่จะเป็น. ssh / agent /) ดังนั้นนี่คือสิ่งที่ฉันลงเอยด้วย: "0 9 * * *. $ HOME / .ssh -agent && rsync -av $ HOME / mydir remote_machine: "
aaron

1
ทั้งหมดนี้ไม่จำเป็นใช้พวงกุญแจ
cmcginty

@cmcginty ผู้ที่บอกว่ามีพวงกุญแจอยู่หรือสามารถติดตั้งได้
zb226

19

พวงกุญแจคือสิ่งที่คุณต้องการ! เพียงติดตั้งและเพิ่มรหัสติดตามใน.bash_profile(หรือเทียบเท่า) ของคุณ:

if [ -x /usr/bin/keychain ]; then
  /usr/bin/keychain --quiet --clear $HOME/.ssh/id_rsa
fi

สำหรับ config.fish ( 2 ):

if not status --is-interactive
   keychain --eval --quiet --quick $HOME/.ssh/id_rsa
end

จากนั้นใช้รหัสด้านล่างในสคริปต์ของคุณเพื่อโหลดตัวแปรสภาพแวดล้อม ssh-agent:

. ~/.keychain/`/bin/hostname`-sh

สำหรับปลา:

source $HOME/.keychain/(hostname)-fish

หากคีย์ของคุณมีวลีรหัสผ่านพวงกุญแจจะถามคุณหนึ่งครั้ง (ใช้ได้จนกระทั่งคุณรีบูทเครื่องหรือฆ่าเอสเอสเอช)

หมายเหตุ: พวงกุญแจยังสร้างรหัสไปยังcshและfishเชลล์ด้วยดังนั้นเพียงแทนที่คำต่อท้าย "-sh" เป็น "-csh" หรือ "-fish"


1
$ HOSTNAME ไม่ได้กำหนดไว้ในสภาพแวดล้อม cron แต่นอกเหนือจากนี้เป็นทางออกที่ดีที่สุด
cmcginty

ถ้าฉันใช้ rsa keys ฉันจะเปลี่ยน keychain ~ / .ssh / id_dsa เป็น keychain ~ / .ssh / id_rsa หรือไม่
Katafalkas

@ Katafalkas แน่นอน!
semente

@Casey ฉันได้อัปเดตคำตอบของฉันแล้ว ตอนนี้เข้ากันได้กับ cron
semente

ฉันเพิ่มคำแนะนำที่ดีกว่าสำหรับปลา
Elijah Lynn

2

ฉันมีตัวแทนไม่มากพอที่จะโหวตคำตอบแรก แต่มันแก้ไขปัญหาที่ฉันมี ในแง่ของ ssh-agent คุณอาจมีหนึ่งกำลังทำงานอยู่ ต่อไปนี้เป็นสคริปต์สำหรับแยก SSH_AGENT_PID & SSH_AUTH_SOCK จากสภาพแวดล้อมโดยไม่มีสิ่งใดเพิ่มเติมเพื่อบันทึกเมื่อเริ่มต้น ssh-agent (สมมติว่าคุณมี Perl)

ใส่ต่อไปนี้ในสคริปต์ (เช่น findagent.pl)

และภายในสคริปต์ cron ของคุณเพิ่มบรรทัด:

`{path to script} eval / findagent.pl`


\#!/usr/bin/perl -w
use strict;
my $agents = `ls -tr /tmp/ssh-*/*`;
my @agents;
(@agents) = split/\n/,$agents;

my $sshpid = `ps aux|grep ssh-agent|grep -v grep|awk '{print \$2}'|head -1`;
chomp($sshpid);
my @parts;
for (@agents) {
  chomp($_);
  if (!$_) { next; }
  my $agentfile = $_;
  (@parts) = split/\./,$agentfile;
  my $masterpid = `ps aux|grep $parts[1]|grep enlightenment`;
  if ($agentfile =~ m/$parts[1]/) {
    my $line1 = "SSH_AUTH_SOCK=" . $agentfile . '; export SSH_AUTH_SOCK';
    my $line2 = 'SSH_AGENT_PID=' . $sshpid . '; export SSH_AGENT_PID;';
    my $line3 = 'echo Agent pid ' . $sshpid . ';';
    print("$line1\n$line2\n$line3\n");
    last;
  } else {
    next;
  }
}

1

ฉันสมมติว่าคุณกำลังใช้การรับรองความถูกต้องตามคีย์เพื่อตรวจสอบตัวเองด้วยเครื่องระยะไกล ลองบรรทัดด้านล่าง:

rsync -av --delete -e "ssh -i .ssh/id_rsa" mydir user@host.tld:~/backupDir

โดยที่. ssh / id_rsa เป็นเส้นทางไปยังคีย์ส่วนตัวของคุณ นี่คือบรรทัดที่แน่นอนที่ฉันใช้ในการสำรองข้อมูลและทำงานได้ดีสำหรับฉันเสมอ

ด้วยความปรารถนาดี
เฟเบียน


0

เป็นทางเลือกแทนการใช้ตัวแทน ssh ฉันทำให้สคริปต์ของฉันส่งออก RSYNC_RSH = "ssh -i /home/user/.ssh/id_rsa" unset SSH_AGENT_PID ยกเลิกการตั้งค่า SSH_AUTH_SOCK ก่อนที่จะเรียกใช้ rsync ด้วยการวางไว้ใน RSYNC_RSH แทนที่จะใช้ '-e ... ' ทำให้ง่ายต่อการปรับไฟล์ id ที่ใช้งานตามโฮสต์

หวังว่านี่จะช่วยได้ข


ฉันไม่คิดว่ามันจะทำงานได้ถ้าคุณมีข้อความรหัสผ่านที่สำคัญ
cmcginty
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.