【问题标题】:How to run a csh script from a sh script如何从 sh 脚本运行 csh 脚本
【发布时间】:2014-01-28 18:30:21
【问题描述】:

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

script1.sh:

#!/bin/sh

source script2

脚本2:

#!/bin/csh -f

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

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

【问题讨论】:

    标签: linux bash shell csh


    【解决方案1】:

    而不是source script2 运行它:

    csh -f script2
    

    【讨论】:

      【解决方案2】:

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

      #!/bin/sh
      
      if [ "$csh_executed" -ne 1 ]; then
          csh_executed=1 exec csh -c "source script2;
                                      exec /bin/sh \"$0\" \"\$argv\"" "$@"
      fi
      
      # rest of script1
      

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


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

      【讨论】:

        【解决方案3】:

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

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

        script2
        

        【讨论】:

          【解决方案4】:

          最接近采购与原始脚本不同的执行程序的脚本是使用execexec 将用新进程替换正在运行的进程空间。然而,与source 不同的是,当您的exec-ed 程序结束时,整个过程结束。所以你可以这样做:

          #!/bin/sh
          
          exec /path/to/csh/script
          

          但你不能这样做:

          #!/bin/sh
          
          exec /path/to/csh/script
          some-other-command
          

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

          #!/bin/sh
          
          csh -f /path/to/csh/script
          some-other-command
          

          【讨论】:

          • 感谢您提供的信息丰富的回答。阅读您的答案后,我发现我打算将其作为子进程运行。请原谅我的匆忙,但我仍然习惯于发帖。
          【解决方案5】:

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

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

          您最好的选择是简单地编写一个新版本的 csh 脚本作为 sh 脚本,并从调用 sh 脚本中 source.

          你可以翻译你的 csh 脚本:

          #!/bin/csh -f
          
          setenv TEST 1234
          set path = /home/user/sandbox
          

          到这里:

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

          (csh 专门处理 shell 数组变量 $path,将其绑定到环境变量 $PATH。sh 及其派生词不这样做,它们直接处理 $PATH 本身。)

          请注意,要获取源的脚本不应在顶部有#! 行,因为在自己的进程中执行它没有意义;你需要在调用者的上下文中执行它的内容。

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

          eval `./foo.csh`
          

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

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

          如果一个软件包需要设置一些特殊的环境变量,通常的做法是提供脚本,例如setup.shsetup.csh,这样sh/ksh/bash/zsh用户可以这样做:

          . /path/to/package/setup.sh
          

          而 csh/tcsh 用户可以这样做:

          source /path/to/package/setup.csh
          

          顺便说一句,这个命令:

          set path = /home/user/sandbox
          

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

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

          或者,在 sh 中:

          PATH=$PATH:/home/user/sandbox
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-06-10
            • 2018-11-15
            • 1970-01-01
            • 2019-11-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-09-12
            相关资源
            最近更新 更多