如何在bash中生成csh脚本以设置环境

如何在bash中生成csh脚本以设置环境,bash,csh,Bash,Csh,我们在Solaris上运行Oracle,shell默认为csh。因此,登录脚本也会在csh中设置oracle_home和oracle_sid。但是我不喜欢csh,我想用bash来完成我的工作。那么,如何在bash中获取csh登录脚本的源代码呢 e、 下面是.cshrc文件中的内容。当使用bash时,我希望使用这些变量。一种方法是再次复制变量并使用bash命令,例如export ORACLE_SID=TEST。但这样做需要我们保存两份文件副本。当我们更改数据库名称或升级数据库时,我需要单独维护ba

我们在Solaris上运行Oracle,shell默认为csh。因此,登录脚本也会在csh中设置oracle_home和oracle_sid。但是我不喜欢csh,我想用bash来完成我的工作。那么,如何在bash中获取csh登录脚本的源代码呢

e、 下面是.cshrc文件中的内容。当使用bash时,我希望使用这些变量。一种方法是再次复制变量并使用bash命令,例如export ORACLE_SID=TEST。但这样做需要我们保存两份文件副本。当我们更改数据库名称或升级数据库时,我需要单独维护bash登录文件。使用这样的东西很好

cshr,但它不起作用

setenv ORACLE_SID TEST setenv ORACLE_HOME /oracle/TEST/home/products/10204 setenv EPC_DISABLED TRUE setenv MANPATH /usr/local/man:/usr/share/man setenv EDITOR vi setenv LD_LIBRARY_PATH $ORACLE_HOME/lib:/usr/sfw/lib/64 setenv NLS_LANG AMERICAN_AMERICA.UTF8 setenv NLS_DATE_FORMAT "DD-MON-RR" setenv ORACLE_SID测试 setenv ORACLE_HOME/ORACLE/TEST/HOME/products/10204 setenv EPC_已禁用为真 setenv MANPATH/usr/local/man:/usr/share/man setenv编辑器vi setenv LD_LIBRARY_PATH$ORACLE_HOME/lib:/usr/sfw/lib/64 setenv NLS_LANG AMERICAN_AMERICA.UTF8 setenv NLS_日期_格式“DD-MON-RR”
我能想到的唯一方法是加载csh,然后从新的shell调用bash。这样,csh可以解析该文件,然后它生成的bash也将继承该环境。

在bash中寻找csh文件将不起作用。如果在bash中更容易使用,可以将默认登录shell从csh更改为bash。您可以使用chsh或作为管理员为您更改它

chsh -s /usr/local/bin/bash 

在您的
~/.bashrc
(或
~/.bash\u配置文件
~/.bash\u登录名
,以及存在的
~/.profile
中的第一个)中,使用类似于
的内容来编写此脚本~/bin/sourcecsh

#!/bin/bash
# This should be sourced rather than executed
while read cmd var val
do
    if [[ $cmd == "setenv" ]]
    then
        eval "export $var=$val"
    fi
done < ~/.cshrc
编辑:

无采购标准:

while read cmd var val
do
    if [[ $cmd == "setenv" ]]
    then
        declare -x "$var=$val"
    fi
done < cshrc
读取cmd var val时
做
如果[$cmd==“setenv”]]
然后
声明-x“$var=$val”
fi
完成
在bash
.profile
中,您可以执行以下操作:

cat .cshrc | sed 's/setenv\s+(\S+)\s+(.*)$/set $1=$2; export $1/' > $HOME/.env_from_csh
source $HOME/.env_from_csh
只要在CSH脚本的开头有一个“
#!/bin/tcsh
”或类似的语句,并使脚本可执行,我就解决了这个问题。在本例中,我可以直接从bash调用CSH脚本

例如,我必须从名为setup.sh的bash脚本运行tools.csh。我在bash脚本中做了如下操作:

if [ -z \`head -1 tools.csh | grep '^#!'\` ];
then
   TCSH=\`which tcsh\`;
   echo "'#!'$TCSH" > tools.csh.temp;
   cat tools.csh >> tools.csh.temp;
   mv tools.csh.temp tools.csh;
fi;
chmod 755 tools.csh;
./tools.csh
# now I have all the setenv commands effective ...

像这样定义一个名为setenv的函数怎么样

setenv() {
  echo setting $1 to $2
  export $1=$2
}
然后寻找.cshrc文件的来源

当我在bash中这样做时,我得到

[dws@oxygen ual-read-only]$ source cshrc
setting ORACLE_SID to TEST
setting ORACLE_HOME to /oracle/TEST/home/products/10204
setting EPC_DISABLED to TRUE
setting MANPATH to /usr/local/man:/usr/share/man
setting EDITOR to vi
setting LD_LIBRARY_PATH to /oracle/TEST/home/products/10204/lib:/usr/sfw/lib/64
setting NLS_LANG to AMERICAN_AMERICA.UTF8
setting NLS_DATE_FORMAT to DD-MON-RR
[dws@oxygen ual-read-only]$ env | grep ORACLE
ORACLE_SID=TEST
ORACLE_HOME=/oracle/TEST/home/products/10204

我也在同一条船上。一位同事向我展示了以下内容:

cat .cshrc | sed 's/setenv\s+(\S+)\s+(.*)$/set $1=$2; export $1/' > $HOME/.env_from_csh
source $HOME/.env_from_csh
从bash开始,不要在环境中使用这些东西:

bash> echo $$
12632
bash> echo $FOO
以下是获取源代码的csh文件:

bash> cat setup-env.csh
setenv FOO "some csh stuff"
echo FOO=$FOO in csh
命令如下:

bash> csh -c 'source setup-env.csh;exec bash'
看看csh的输出

FOO=some csh stuff in csh
并查看新bashshell的输出

  bash> echo $$
  13487
  bash> echo $FOO
  some csh stuff
bash> exit
exit
bash> echo $$
12632
bash> 
现在离开,回到原来的bashshell

  bash> echo $$
  13487
  bash> echo $FOO
  some csh stuff
bash> exit
exit
bash> echo $$
12632
bash> 
请注意echo$$以查看进程ID,以便我们可以看到它们是不同的shell进程

我的同事用得够多了,他把它放到了一个别名中,比如:

# make csh environment scripts useable (sourceable) from bash function 
# from Phil McCoy, Wed Nov  9 2011
source_csh () {
   exec csh -c " source $*; setenv ALREADY_SOURCED \"$ALREADY_SOURCED:$*:\"; exec bash"
}
# sounds like a great idea to do source_csh .cshrc or .login
# but naively done is infinitely recursive, 
# since the exec'ed bash will run .bashrc
不幸的是,我发现我经常不仅需要环境变量设置,还需要别名设置,就像在modules包中一样


通过使用Perl Expect,我已经能够自动化这个“csh源代码脚本配方”。但是除了上面提到的,我还不能像我所希望的那样进行交互。

对于这么小的东西,维护两个设置脚本是很常见的,一个用于sh和sh派生的shell,另一个用于csh和tcsh。正如您所提到的,这确实会造成两个脚本不同步的风险——除非您从另一个脚本生成一个脚本,或者从公共源生成两个脚本


这会给安装脚本的维护人员带来负担,而不是给每个需要使用它们的用户带来负担。

有一个可用的模块,您可以在perl脚本中的任何地方获取相同的文件。您将在csh文件中获得所有可用的环境路径

Source::Shell

浏览一些文档了解其用法。

更适合超级用户或服务器故障?@Dennis-nice。。。我喜欢这个,因为它是纯bash(我的使用
sed
)。。。我必须承认,我仍然更喜欢我的版本(相当类似),主要是因为它将set命令列表作为一个文件保存,以便以后进行故障排除或环境恢复,以防万一:)我将投票支持第一个版本——sourcing stdin至少和
eval
一样容易出问题。它也很酷,我不喜欢创建一些垃圾文件。不确定是否可以使用管道来避免临时文件。无用地使用
cat
。Bash不以这种方式使用
set
<代码>导出可以同时获取变量名和赋值。您必须使用不同版本的
sed
,因为它看起来像Perl语法。您需要使用
-r
或将括号和加号转义。您可以删除这样的临时文件:
source/dev/stdin<@Dennis和Daniel-我通常想要那个“垃圾”临时文件:)
source/dev/stdin(cat.cshrc;echo exec$SHELL)|csh
如果
/tools.csh
设置了环境变量,则它们在调用SHELL中不可见。如果依赖于这些环境变量的命令都在
/tools.csh
中,那没关系。我非常喜欢modules包,我很惊讶有更多的人不使用它。让贝壳不可知只是一件很好的事情。接近但没有雪茄。(1) 一些csh源代码脚本设置别名——我不知道如何将别名从csh导出回调用shell(如bash)。我认为将任何csh别名转换为bash别名,或者将任何csh别名转换为bash别名(后者用于调用新的csh源代码脚本),这只是一个简单的编程问题。(2) 因为我的普通登录shell有额外的encvironmenht变量,所以我需要先清空它。这就是我要问的。(3) 哦,我刚刚注意到了你在做什么:是的,我在bash有一个setenv已经很多年了。(实际上,在bash出现之前,在ksh中)