Linux 如何从 sh 脚本运行 csh 脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21413876/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 01:55:22  来源:igfitidea点击:

How to run a csh script from a sh script

linuxbashshellcsh

提问by user3245776

I was wondering if there is a way to source a csh script from a sh script. Below is an example of what is trying to be implemented:

我想知道是否有办法从 sh 脚本中获取 csh 脚本。以下是尝试实施的示例:

script1.sh:

脚本1.sh:

#!/bin/sh

source script2

script2:

脚本2:

#!/bin/csh -f

setenv TEST 1234
set path = /home/user/sandbox

When I run sh script1.sh, I get syntax errors generated from script2 (expected since we are using a different Shebang). Is there a way I can run script2 through script1?

当我运行 sh script1.sh 时,我收到了由 script2 生成的语法错误(因为我们使用的是不同的 Shebang,所以是预期的)。有没有办法通过script1运行script2?

采纳答案by anubhava

Instead of source script2run it as:

而不是source script2运行它:

csh -f script2

回答by Wooble

You don't want sourcethere; it runs the given script inside your existing shell, without spawning a subprocess. Obviously, your sh process can't run something like that which isn't a sh script.

你不想source在那里;它在您现有的 shell 中运行给定的脚本,而不产生子进程。显然,您的 sh 进程不能运行类似 sh 脚本的程序。

Just call the script directly, assuming it is executable:

直接调用脚本,假设它是可执行的:

script2

回答by chepner

Since your use case depends on retaining environment variables set by the cshscript, try adding this to the beginning of script1:

由于您的用例取决于保留csh脚本设置的环境变量,请尝试将其添加到开头script1

#!/bin/sh

if [ "$csh_executed" -ne 1 ]; then
    csh_executed=1 exec csh -c "source script2;
                                exec /bin/sh \"
#!/bin/sh

exec /path/to/csh/script
\" \"$argv\"" "$@" fi # rest of script1

If the csh_executedvariable is not set to 1 in the environment, run a cshscript that sources script2then executes an instance of sh, which will retain the changes to the environment made in script2. execis used to avoid creating new processes for each shell instance, instead just "switching" from one shell to the next. Setting csh_executedin the environment of the cshcommand ensures that we don't get stuck in a loop when script1is re-executed by the cshinstance.

如果csh_executed在环境变量未设置为1,运行一个csh脚本来源script2然后执行的实例sh,这将保留更改中所做的环境script2exec用于避免为每个外壳实例创建新进程,而只是从一个外壳“切换”到下一个。csh_executedcsh命令的环境中设置可以确保我们在script1csh实例重新执行时不会陷入循环。



Unfortunately, there is one drawback that I don't think can be fixed, at least not with my limited knowledge of csh: the second invocation of script1receives all the original arguments as a single string, rather than a sequence of distinct arguments.

不幸的是,有一个我认为无法修复的缺点,至少在我对 的有限知识的情况下无法修复csh:第二次调用将script1所有原始参数作为单个字符串接收,而不是一系列不同的参数。

回答by kojiro

The closest you can come to sourcinga script with a different executor than your original script is to use exec. execwill replace the running process space with the new process. Unlike source, however, when your exec-ed program ends, the entire process ends. So you can do this:

使用与原始脚本不同的执行程序来获取脚本的最接近方法是使用exec. exec将用新进程替换正在运行的进程空间。source但是,与 不同的是,当您的exec-ed 程序结束时,整个过程就结束了。所以你可以这样做:

#!/bin/sh

exec /path/to/csh/script
some-other-command

but you can't do this:

但你不能这样做:

#!/bin/sh

csh -f /path/to/csh/script
some-other-command

However, are you sure you really want to sourcethe script? Maybe you just want to run it in a subprocess:

但是,您确定真的要获取脚本的来源吗?也许您只想在子进程中运行它:

#!/bin/csh -f

setenv TEST 1234
set path = /home/user/sandbox

回答by Keith Thompson

You want the settings in your csh script to apply to the sh script that invokes it.

您希望 csh 脚本中的设置应用于调用它的 sh 脚本。

Basically, you can't do that, though there are some (rather ugly) ways you could make it work. If you executeyour csh script, it will set those variables in the context of the process running the script; they'll vanish as soon as it returns to the caller.

基本上,你不能这样做,尽管有一些(相当丑陋的)方法可以让它工作。如果您执行csh 脚本,它将在运行脚本的进程的上下文中设置这些变量;一旦返回给调用者,它们就会消失。

Your best bet is simply to write a new version of your csh script as an sh script, and sourceor .it from the calling sh script.

最好的办法是简单地将 csh 脚本的新版本编写为 sh 脚本source或者.从调用 sh 脚本编写。

You could translate your csh script:

你可以翻译你的 csh 脚本:

export TEST=1234
export PATH=/home/user/sandbox

to this:

对此:

eval `./foo.csh`

(csh treats the shell array variable $pathspecially, tying it to the environment variable $PATH. sh and its derivatives don't do that, they deal with $PATHitself directly.)

(csh$path特殊对待 shell 数组变量,将其绑定到环境变量$PATH。sh 及其派生类不这样做,它们$PATH直接处理自身。)

Note that a script intended to be sourced should nothave a #!line at the top, since it doesn't make sense to execute it in its own process; you need to execute its contents in the context of the caller.

需要注意的是脚本旨在来源应该不是有一个#!顶部线,因为它没有意义在自己的进程来执行它; 您需要在调用者的上下文中执行其内容。

If maintaining two copies of the script, one to be sourced from csh or tcsh scripts and another to be sourced or .ed from sh/ksh/bash/zsh script, is not practical, there are other solutions. For example, your script can print a series of shcommands to be executed; you can then do something like

如果维护脚本的两个副本,一个source从 csh 或 tcsh 脚本sourced和另一个.从 sh/ksh/bash/zsh 脚本d 或ed 不切实际,还有其他解决方案。例如,您的脚本可以打印一系列sh要执行的命令;然后你可以做类似的事情

. /path/to/package/setup.sh

(line endings will pose some issues here).

(行尾会在这里造成一些问题)。

Or you can modify the csh script so it sets the required environment variables and then invokes some specified command, which could be a new interactive shell; this is inconvenient, since it doesn't set those variables in the interactive shell you're running.

或者你可以修改 csh 脚本,让它设置所需的环境变量,然后调用一些指定的命令,它可以是一个新的交互式 shell;这很不方便,因为它不会在您正在运行的交互式 shell 中设置这些变量。

If a software package requires some special environment variables to be set, it's common practice to provide scripts called, for example, setup.shand setup.csh, so that sh/ksh/bash/zsh users can do:

如果某个软件包需要设置一些特殊的环境变量,通常的做法是提供称为setup.shand 的脚本setup.csh,以便 sh/ksh/bash/zsh 用户可以执行以下操作:

source /path/to/package/setup.csh

and csh/tcsh users can do:

和 csh/tcsh 用户可以:

set path = /home/user/sandbox

Incidentally, this command:

顺便说一句,这个命令:

set path = ( $path /home/user/sandbox )

in your sample script is probably not a good idea. It replacesyour entire $PATHwith just a single directory, which means you won't be able to execute simple commands like lsunless you specify their full paths. You'd usually want something like:

在您的示例脚本中可能不是一个好主意。它只$PATH一个目录替换了整个目录,这意味着ls除非指定完整路径,否则您将无法执行简单的命令。你通常想要这样的东西:

PATH=$PATH:/home/user/sandbox

or, in sh:

或者,在 sh 中:

##代码##