我的 perl 腳本 z.pl 使用
Time::Local qw( timelocal_posix timegm_posix );
和
File::Rsync. (你會在這篇文章的底部找到 z.pl。)
目前我在 macOS Catalina 10.15.7 下的 macbook pro 上作業。但我希望我的代碼是可移植的,以便將來,如果我將檔案移動到不同的機器或作業系統(或至少另一個 *nix),代碼將不需要修復 --- 除了可能的更改在源路徑和目標路徑中。為此,我通常的shebang是
#!/usr/bin/env perl。
要訪問
Time::Local qw( timelocal_posix timegm_posix );
我必須安裝最新版本的 perl。(為此,我使用了自制軟體。)這是因為我的 macbook pro 上加載的 perl 已經過時了。我們在這里看到了不同之處:
> /usr/bin/perl --version
This is perl 5, version 18, subversion 4 (v5.18.4) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)
Copyright 1987-2013, Larry Wall
> /usr/bin/env perl --version
This is perl 5, version 34, subversion 0 (v5.34.0) built for darwin-thread-multi-2level
Copyright 1987-2021, Larry Wall
> /usr/local/bin/perl --version # same as previous
This is perl 5, version 34, subversion 0 (v5.34.0) built for darwin-thread-multi-2level
我們在這里看到舊版本沒有我需要的東西:
> /usr/bin/env perl -e 'use Time::Local qw( timelocal_posix timegm_posix );'
> /usr/bin/perl -e 'use Time::Local qw( timelocal_posix timegm_posix );'
"timelocal_posix" is not exported by the Time::Local module
"timegm_posix" is not exported by the Time::Local module
Can't continue after import errors at -e line 1.
BEGIN failed--compilation aborted at -e line 1.
我希望這段代碼每小時作業一次。為此,可以打開命令列并鍵入
while [ : ]; do z.pl; sleep 3600; done
然后它大約每小時運行一次。但這需要用戶記住每次重新啟動計算機時重新啟動命令。這不是自動的。
有人會認為 cron 就是答案。但是當我嘗試用 cron 呼叫它時,第一個障礙是 cron 不知道我的路徑。因此,我的便攜式 shebang 指向過時的 perl。因此,為了讓 z.pl 在 cron 下運行,我對不可移植性做出了讓步,并對 shebang 進行了硬編碼#!/usr/local/bin/perl。
但即使進行了這種修改,rsync 部分還是失敗了。為了證明這一點,我首先在命令列上輸入
~/tmplocal/DUMS> z.pl >> out.txt 2>&1
隨后我臨時修改了我的 crontab 以包括
00 * * * * $HOME/u/kh/bin/z.pl >> $HOME/tmplocal/DUMS/z.pl/out.txt 2>&1
生成的 out.txt 檔案如下。這兩種不同的呼叫不僅可以通過其標頭中的時間戳來區分,還可以通過 PATH 變數中的差異來區分。在 cron 下,腳本不知道我的路徑。
------------------------2021-12-27 Mon 12:52:22------------------------
HOME: /Users/kpr
USER: kpr
PATH: /Users/kpr/u/kh/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin:/Library/Apple/usr/bin
$VAR1 = {
'err' => '',
'lastcmd' => 'rsync --itemize-changes --update --stats --compress --recursive --times --perms --links --verbose --exclude=.swp --exclude=.swo --exclude=.*.swp --exclude=.*.swo --exclude=JAW.gnucash.LCK --exclude=JAW.gnucash.LNK --exclude=JAW.gnucash*log /Users/kpr/TEMPBACKUP /Volumes/oom/quick',
'out' => 'building file list ... done
.d..t.... TEMPBACKUP/2021/2021d/
>f TEMPBACKUP/2021/2021d/2021-12-27-125000-z.pl
>f TEMPBACKUP/2021/2021d/2021-12-27-125026-z.pl
>f TEMPBACKUP/2021/2021d/2021-12-27-125055-z.pl
>f TEMPBACKUP/2021/2021d/2021-12-27-125211-z.pl
Number of files: 184014
Number of files transferred: 4
Total file size: 60206266413 bytes
Total transferred file size: 7596 bytes
Literal data: 7596 bytes
Matched data: 0 bytes
File list size: 7048863
File list generation time: 16.863 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 7052167
Total bytes received: 114
sent 7052167 bytes received 114 bytes 328013.07 bytes/sec
total size is 60206266413 speedup is 8537.13
',
'realstatus' => 0,
'status' => 0
};
------------------------2021-12-27 Mon 13:00:01------------------------
HOME: /Users/kpr
USER: kpr
PATH: /usr/bin:/bin
$VAR1 = {
'err' => 'rsync: failed to set times on "/Volumes/oom/quick/TEMPBACKUP/2021/2021d": Operation not permitted (1)
rsync: mkstemp "/Volumes/oom/quick/TEMPBACKUP/2021/2021d/.2021-12-27-125615-month060.tex.qZ6XYt" failed: Operation not permitted (1)
rsync: mkstemp "/Volumes/oom/quick/TEMPBACKUP/2021/2021d/.2021-12-27-125720-junk.mvgt5F" failed: Operation not permitted (1)
rsync: failed to set times on "/Volumes/oom/quick/TEMPBACKUP/2021/2021d": Operation not permitted (1)
rsync error: some files could not be transferred (code 23) at /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/rsync/rsync-54.120.1/rsync/main.c(996) [sender=2.6.9]
',
'lastcmd' => 'rsync --itemize-changes --update --stats --compress --recursive --times --perms --links --verbose --exclude=.swp --exclude=.swo --exclude=.*.swp --exclude=.*.swo --exclude=JAW.gnucash.LCK --exclude=JAW.gnucash.LNK --exclude=JAW.gnucash*log /Users/kpr/TEMPBACKUP /Volumes/oom/quick',
'out' => 'building file list ... done
.d..t.... TEMPBACKUP/2021/2021d/
>f TEMPBACKUP/2021/2021d/2021-12-27-125615-month060.tex
>f TEMPBACKUP/2021/2021d/2021-12-27-125720-junk
Number of files: 184016
Number of files transferred: 2
Total file size: 60206953341 bytes
Total transferred file size: 686928 bytes
Literal data: 686928 bytes
Matched data: 0 bytes
File list size: 7048935
File list generation time: 18.892 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 7272636
Total bytes received: 70
sent 7272636 bytes received 70 bytes 285204.16 bytes/sec
total size is 60206953341 speedup is 8278.48
',
'realstatus' => 5888,
'status' => 23
};
這是z.pl:
#!/usr/local/bin/perl # 2021v12v26vSunv18h08m02s for cron, which does not know my environment
##!/usr/bin/env perl # does not have the required packages under cron
use strict; use warnings;
use Data::Dumper qw(Dumper); $Data::Dumper::Sortkeys = 1;
use Time::Local qw( timelocal_posix timegm_posix ); use POSIX qw(strftime);
select STDERR; # so that STDERR and STDOUT will appear in the proper order; without this, STDERR comes before STDOUT
my $epoch_s=time;
my $dateJ =(strftime '%Y-%m-%d %a %H:%M:%S', localtime($epoch_s));
print
"\n",
'------------',
'------------',
$dateJ,
'------------',
'------------',
"\n",
;
print 'HOME: ',$ENV{HOME},"\n";
print 'USER: ',$ENV{USER},"\n";
print 'PATH: ',$ENV{PATH},"\n";
my%subvar;
$subvar{src}=join('/',$ENV{HOME},'TEMPBACKUP');
unless(-r$subvar{src} and -w$subvar{src} and -d$subvar{src})
{
die $subvar{src},q#: unless(-r$subvar{src} and -w$subvar{src} and -d$subvar{src})#;
}
$subvar{dest}=q#/Volumes/oom/quick#;
unless(-r$subvar{dest} and -w$subvar{dest} and -d$subvar{dest})
{
die $subvar{dest},q#: unless(-r$subvar{dest} and -w$subvar{dest} and -d$subvar{dest})#;
}
use File::Rsync;
my $FileRsync=File::Rsync->new(
itemize_changes=>1,
delete =>0,
update =>1,
stats =>1,
compress =>1,
recursive =>1,
times =>1,
perms =>1,
links =>1,
verbose =>1,
exclude =>['.swp','.swo','.*.swp','.*.swo','JAW.gnucash.LCK','JAW.gnucash.LNK','JAW.gnucash*log',],
);
$FileRsync->exec(
src=>$subvar{src},
,
dest=>$subvar{dest},
);
$subvar{rsync}{out}='';$subvar{rsync}{out}=join('',@{$FileRsync->out})if(defined$FileRsync->out);
$subvar{rsync}{err}='';$subvar{rsync}{err}=join('',@{$FileRsync->err})if(defined$FileRsync->err);
$subvar{rsync}{status}=$FileRsync->status;
$subvar{rsync}{realstatus}=$FileRsync->realstatus;
$subvar{rsync}{lastcmd}=$FileRsync->lastcmd;
print Dumper$subvar{rsync};
有沒有辦法讓 cron 使用它?還是應該使用 cron 以外的其他工具?
uj5u.com熱心網友回復:
要啟動 shell 并讓它運行其登錄腳本,您首先需要一個 shell,使用以下命令:
/bin/sh -l -c '...shell cmd...'
您還可以在 crontab 中設定環境變數,但這可能更容易。
uj5u.com熱心網友回復:
這個對我自己問題的回答只是填寫了@ikegami 解決方案的詳細資訊。我希望這是正確的協議,而不是編輯@ikegami 的作業。
首先,在https://unix.stackexchange.com/questions/308907/how-to-set-shell-bin-bash-globally-for-cron 我們發現以下內容:
無法為 cron 作業設定全域默認 shell。
這似乎解釋了為什么 cron “不知道我的路徑”。我習慣的路徑是bash shell自動設定的互動式路徑。正如 https://linuxhint.com/path_in_bash/ 所說:
默認情況下,PATH 變數包含以下位置。
/usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /bin /sbin /snap/bin (如果安裝了 Snap)
但是cron shell 是/bin/sh;這就是為什么 cron 沒有我通常的路徑。
現在,感謝@ikegami,以下兩個解決方案有效:
> crontab -l
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin:/Library/Apple/usr/bin
00 16 * * * $HOME/u/kh/bin/jaw20200410cronmakeccalfile.sh
45 14 * * * $HOME/u/kh/bin/testcron.pl >> $HOME/tmplocal/DUMS/testcron.pl/out.txt 2>&1
>
以及以下內容,它在 crontab 中少用了一行代碼,也避免了路徑的硬編碼,這很容易導致程式員(我自己的)錯誤:
> crontab -l
00 16 * * * $HOME/u/kh/bin/jaw20200410cronmakeccalfile.sh
55 14 * * * /bin/bash -l -c '$HOME/u/kh/bin/testcron.pl >> $HOME/tmplocal/DUMS/testcron.pl/out.txt 2>&1'
>
請注意,我的問題的第二部分,關于 rsync 和權限,這里沒有回答。既然路徑已修復,我將不得不重新調查。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/399094.html
上一篇:模板引數檢查的通用方法
