简体   繁体   English

如何在 bash 命令行上运行脚本,使其配置与 cron 运行时的配置相同?

[英]how can I run a script at the bash command line such that its configuration is identical to its configuration when it is run by cron?

I want to write and test scripts that do not depend on any of the personal environment variables accessible to me at the command line.我想编写和测试不依赖于我在命令行可访问的任何个人环境变量的脚本。 For instance, each time I open a new command line window on my macbook pro, $PATH is updated by having my personal bin directory prepended to it --- as well as several other directories, such as例如,每次我在我的 macbook pro 上打开一个新的命令行 window 时, $PATH都会通过在其前面加上我的个人 bin 目录来更新 --- 以及其他几个目录,例如

/usr/sbin:/sbin:/Library/TeX/texbin:/Library/Apple/usr/bin

This occurs apparently because my $HOME/.profile is automatically sourced when a window opens up.这显然是因为我的 $HOME/.profile 是在 window 打开时自动获取的。 In addition, a large number of other variables are defined at login because my personal.bashrc is sourced automatically.另外,由于我的personal.bashrc是自动获取的,所以登录时定义了大量其他变量。

Ultimately, I want to be able to run a script as a cron job --- using crontab -l .最终,我希望能够使用crontab -l将脚本作为 cron 作业运行。 But if the script depends on my personal configuration, or if it tries to access a script that lives in my personal bin, it will halt with error.但是,如果脚本取决于我的个人配置,或者如果它试图访问我个人 bin 中的脚本,它将因错误而停止。

So I write a script, test it at the command line, set up a cron job to run it;所以我写了一个脚本,在命令行测试它,设置一个cron作业来运行它; and when the time comes, it halts with error, because it turns out that the script depended on one of my personal environment variables.当时机成熟时,它会因错误而停止,因为事实证明该脚本依赖于我的个人环境变量之一。

Currently, then, the only way I know to test such a script is to set up a cron job --- say, five minutes from now---and then wait for the cron job to run.目前,我知道测试这样一个脚本的唯一方法是设置一个 cron 作业——比如说,从现在开始五分钟——然后等待 cron 作业运行。 It's clumsy and slow.它笨拙而缓慢。

Is there a direct and immediate way to run a script so that it does not know anything from $HOME/.profile?是否有直接和直接的方法来运行脚本,使其不知道 $HOME/.profile 中的任何内容?

The script I tested this with:我测试的脚本:

#!/usr/bin/perl
use strict; use warnings;
use Data::Dumper qw(Dumper);
$Data::Dumper::Sortkeys = 1;
print Dumper {%ENV};

The following command以下命令

> jaw20210419test.pl | wc
    2532    3098  118462

produces many lines of output, as you see, because of all that I define in my.bashrc.如您所见,由于我在 my.bashrc 中定义的所有内容,生成了多行 output。 With the following,有了以下内容,

> sudo jaw20210419test.pl | wc
Password:
      20      59     831
> 

the output is much less, but it still has an updated $PATH including my personal bin. output 少得多,但它仍然有更新的$PATH包括我的个人 bin。 I do not understand this, since the $PATH gets updated by $HOME/.profile, and that file sources my personal $HOME/u/kh/.bashrc.我不明白这一点,因为$PATH由 $HOME/.profile 更新,并且该文件来自我个人的 $HOME/u/kh/.bashrc。

If however I run this with a cron job, then it does not have an updated $PATH .但是,如果我使用 cron 作业运行它,那么它没有更新的$PATH The script says剧本说

$VAR1 = {
          'HOME' => '/Users/kpr',
          'LOGNAME' => 'kpr',
          'PATH' => '/usr/bin:/bin',
          'PWD' => '/Users/kpr',
          'SHELL' => '/bin/sh',
          'SHLVL' => '1',
          'USER' => 'kpr',
          'VERSIONER_PERL_VERSION' => '5.18',
          '_' => '/Users/kpr/u/kh/bin/jaw20210419test.pl',
          '__CF_USER_TEXT_ENCODING' => '0x1F5:0x0:0x0'
        };

This is the configuration I want to test the script with.这是我想用来测试脚本的配置。 Note that it knows who I am --- $USER --- and where $HOME is.请注意,它知道我是谁 --- $USER --- 以及$HOME在哪里。

By contrast, two other proposed solutions, from How to start a shell without any user configuration?相比之下,另外两个提出的解决方案,从如何在没有任何用户配置的情况下启动 shell? , do not even know know where $HOME is: ,甚至不知道$HOME在哪里:

> echo $cdbin # personal environment variable
/Users/kpr/u/kh/bin
> env -i perl $cdbin/jaw20210419test.pl 
$VAR1 = {
          'VERSIONER_PERL_VERSION' => '5.18',
          '__CF_USER_TEXT_ENCODING' => '0x1F5:0x0:0x0'
        }; 
> env --noprofile --norc  perl $cdbin/jaw20210419test.pl 
env: illegal option -- n
usage: env [-iv] [-P utilpath] [-S string] [-u name]
           [name=value ...] [utility [argument ...]]
> echo $SHELL
/bin/bash
> 
> env -i sh -c  $cdbin/jaw20210419test.pl 
$VAR1 = {
          'PWD' => '/Users/kpr/u/sng/2021/FR-Wegelin-TO-stackoverflow',
          'SHLVL' => '1',
          'VERSIONER_PERL_VERSION' => '5.18',
          '_' => '/Users/kpr/u/kh/bin/jaw20210419test.pl',
          '__CF_USER_TEXT_ENCODING' => '0x1F5:0x0:0x0'
        };

so I am still lost.所以我还是迷路了。

Of note, you can not technically do what you wish.值得注意的是,从技术上讲,您无法按照自己的意愿行事。 Bash goes to great lengths to determine if you are running an interactive shell or a non-interactive shell. Bash 竭尽全力确定您是在运行交互式 shell 还是非交互式 shell。 Running from cron will forever be non-interactive as is running from a terminal will forever be marked as interactive.从 cron 运行将永远是非交互式的,因为从终端运行将永远被标记为交互式。

You want a number of entries not present in cron for your test shell, for example PS1 for a prompt.对于测试 shell,您希望 cron 中不存在许多条目,例如 PS1 用于提示。 Also there are quite a few read only environment variables.还有很多只读环境变量。 If you try to unset them you get an error:如果您尝试取消设置它们,则会收到错误消息:

bash: unset: SHELLOPTS: cannot unset: readonly variable

You can get 95 percent there by this method:您可以通过这种方法获得 95%:

% env -i bash --noprofile --norc
bash-3.2$ source be-cron.sh
bash-3.2$

The file be-cron.sh will "unset" most of the interactive environment variables:文件be-cron.sh将“取消设置”大多数交互式环境变量:

#!/bin/bash
unset BASH
unset BASH_ENV
unset BASH_VERSION
unset COLORFGBG
unset COLORTERM
unset COLUMNS
unset COMMAND_MODE
unset DIRSTACK
unset DISPLAY
unset EDITOR
unset GROUP
unset GROUPS
unset HISTFILE
unset HISTFILESIZE
unset HISTSIZE
unset HOST
unset HOSTNAME
unset HOSTTYPE
unset IFS
unset ITERM_PROFILE
unset ITERM_SESSION_ID
unset LC_TERMINAL
unset LC_TERMINAL_VERSION
unset LINES
unset LaunchInstanceID
unset MACHTYPE
unset MAILCHECK
unset MANPATH
unset MANPATH_WITHOUT_PERLBREW
unset OPTERR
unset OPTIND
unset OSTYPE
unset PATH_WITHOUT_PERLBREW
unset PERLBREW_HOME
unset PERLBREW_PATH
unset PERLBREW_ROOT
unset PERLBREW_SHELLRC_VERSION
unset PIPESTATUS
unset PS2
unset PS4
unset SECURITYSESSIONID
unset SSH_AUTH_SOCK
unset TERM
unset TERM_PROGRAM
unset TERM_PROGRAM_VERSION
unset TERM_SESSION_ID
unset TMPDIR
unset VENDOR
unset XPC_FLAGS
unset XPC_SERVICE_NAME
unset __CFBundleIdentifier

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何运行非阻塞bash命令并阻塞其输出? - How can I run a non-blocking bash command and block on its output? 从cron作业运行时,bash脚本返回的值与从命令行运行时返回的值不同 - Bash script returns different value when run from cron job than from command line 如何制作bash脚本以反向搜索相同的图像并下载其最大分辨率? - How can I make a bash script for reverse searching an identical image and downloading its greatest resolution? 如何使用命令行参数从bash运行perl脚本? - How can I run a perl script from bash using command line arguments? 运行程序以确保文件相同时,如何访问bash中的文件并将其内容与stdout进行比较? - How can I access a file in bash and compare its contents with stdout when running a program to make sure they are identical? 如何在 Bash 脚本中运行 sudo 命令? - How can i run a sudo command in Bash script? 当我运行包含bash脚本中的颜色的命令时,如何获取原始字符串 - How can I get raw string when I run a command that includes color from bash script 如何静默运行外部脚本并检索其退出代码bash - How to run external script silently and retrieve its exit code bash Makefile:如何运行 bash 脚本并忽略其退出状态? - Makefile: how to run bash script and ignore its exit status? 如何将命令行 awk 脚本(带参数)作为 bash 脚本运行? - How to run command line awk script (with arguments) as bash script?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM