| 1 | Article 19995 of comp.lang.perl: |
| 2 | Newsgroups: comp.lang.perl |
| 3 | Path: netlabs!news.cerf.net!mvb.saic.com!MathWorks.Com!europa.eng.gtefsd.com!howland.reston.ans.net!news.ans.net!malgudi.oar.net!chemabs!skf26 |
| 4 | From: skf26@cas.org (Scott Frost) |
| 5 | Subject: HOW TO source shell scripts into Perl |
| 6 | Message-ID: <1994Mar21.191518.11636@chemabs.uucp> |
| 7 | Followup-To: scott.frost@cas.org |
| 8 | Keywords: Shell, Source, Dot |
| 9 | Sender: usenet@chemabs.uucp |
| 10 | Organization: Chemical Abstracts Service |
| 11 | Date: Mon, 21 Mar 1994 19:15:18 GMT |
| 12 | Lines: 139 |
| 13 | |
| 14 | A few days ago I posted a request for information on how to source |
| 15 | a shell script into a perl script. In general, the responses indicated that |
| 16 | it could not be done (although one came pretty close to the actual solution). |
| 17 | |
| 18 | A fellow staff member (who I was posting the request for) wasn't satisfied with |
| 19 | the response and came up with a way. |
| 20 | |
| 21 | Before I indicate how he solved the problem, let me suggest some alternative |
| 22 | methods of resolving this issue, |
| 23 | |
| 24 | 1. Hard code the environment variables directly in your PERL script. This |
| 25 | is easy but unreliable. System administrators could change the |
| 26 | production shell script environment variables and your PERL script would |
| 27 | be hosed. |
| 28 | |
| 29 | 2. Create a shell wrapper that dots the shell script into your current |
| 30 | environment and then invoke your perl script. This approach is easy |
| 31 | to do, fairly full proof, but an affront to serious PERL programmers |
| 32 | who believe PERL is God's gift to man (or at least Larry's :-) ). |
| 33 | |
| 34 | Chuck's solution involves running the script in the appropriate shell |
| 35 | environment, dumping the shell's environment variables to a file, and then |
| 36 | reading the environment variables into PERL's environment. |
| 37 | |
| 38 | It supports ksh, sh, csh, and zsh shells. It'll look at the first line of |
| 39 | the file to be executed to determine the shell to run it under, if not found, |
| 40 | it'll look at the SHELL environment variable. If the shell is not one of the |
| 41 | four listed, it'll warn you and attempt to run the shell script under /bin/sh. |
| 42 | |
| 43 | A typical usage might look like this, |
| 44 | #!/usr/bin/perl |
| 45 | |
| 46 | # Make sure dotsh.pl is placed in your /usr/perl/lib |
| 47 | require "dotsh.pl"; |
| 48 | |
| 49 | print "SHELL_ENV_VAR = $SHELL_ENV_VAR\n" ; |
| 50 | &dotsh('/tmp/foo') ; # script to run |
| 51 | print "SHELL_ENV_VAR = $SHELL_ENV_VAR\n" ; |
| 52 | |
| 53 | /tmp/foo looks like this: |
| 54 | #!/bin/ksh |
| 55 | export SHELL_ENV_VAR="hi mom" |
| 56 | |
| 57 | The actual dotsh.pl script follows (BTW, this is now public domain): |
| 58 | # |
| 59 | # @(#)dotsh.pl 03/19/94 |
| 60 | # |
| 61 | # Author: Charles Collins |
| 62 | # |
| 63 | # Description: |
| 64 | # This routine takes a shell script and 'dots' it into the current perl |
| 65 | # environment. This makes it possible to use existing system scripts |
| 66 | # to alter environment variables on the fly. |
| 67 | # |
| 68 | # Usage: |
| 69 | # &dotsh ('ShellScript', 'DependentVariable(s)'); |
| 70 | # |
| 71 | # where |
| 72 | # |
| 73 | # 'ShellScript' is the full name of the shell script to be dotted |
| 74 | # |
| 75 | # 'DependentVariable(s)' is an optional list of shell variables in the |
| 76 | # form VARIABLE=VALUE,VARIABLE=VALUE,... that 'ShellScript' is |
| 77 | # dependent upon. These variables MUST be defined using shell syntax. |
| 78 | # |
| 79 | # Example: |
| 80 | # &dotsh ('/tmp/foo', 'arg1'); |
| 81 | # &dotsh ('/tmp/foo'); |
| 82 | # &dotsh ('/tmp/foo arg1 ... argN'); |
| 83 | # |
| 84 | sub dotsh { |
| 85 | local(@sh) = @_; |
| 86 | local($tmp,$key,$shell,*dotsh,$command,$args,$vars) = ''; |
| 87 | $dotsh = shift(@sh); |
| 88 | @dotsh = split (/\s/, $dotsh); |
| 89 | $command = shift (@dotsh); |
| 90 | $args = join (" ", @dotsh); |
| 91 | $vars = join ("\n", @sh); |
| 92 | open (_SH_ENV, "$command") || die "Could not open $dotsh!\n"; |
| 93 | chop($_ = <_SH_ENV>); |
| 94 | $shell = "$1 -c" if ($_ =~ /^\#\!\s*(\S+(\/sh|\/ksh|\/zsh|\/csh))\s*$/); |
| 95 | close (_SH_ENV); |
| 96 | if (!$shell) { |
| 97 | if ($ENV{'SHELL'} =~ /\/sh$|\/ksh$|\/zsh$|\/csh$/) { |
| 98 | $shell = "$ENV{'SHELL'} -c"; |
| 99 | } else { |
| 100 | print "SHELL not recognized!\nUsing /bin/sh...\n"; |
| 101 | $shell = "/bin/sh -c"; |
| 102 | } |
| 103 | } |
| 104 | if (length($vars) > 0) { |
| 105 | system "$shell \"$vars;. $command $args; set > /tmp/_sh_env$$\""; |
| 106 | } else { |
| 107 | system "$shell \". $command $args; set > /tmp/_sh_env$$\""; |
| 108 | } |
| 109 | |
| 110 | open (_SH_ENV, "/tmp/_sh_env$$") || die "Could not open /tmp/_sh_env$$!\n"; |
| 111 | while (<_SH_ENV>) { |
| 112 | chop; |
| 113 | /=/; |
| 114 | $ENV{$`} = $'; |
| 115 | } |
| 116 | close (_SH_ENV); |
| 117 | system "rm -f /tmp/_sh_env$$"; |
| 118 | |
| 119 | foreach $key (keys(ENV)) { |
| 120 | $tmp .= "\$$key = \$ENV{'$key'};" if $key =~ /^[A-Za-z]\w*$/; |
| 121 | } |
| 122 | eval $tmp; |
| 123 | } |
| 124 | 1; |
| 125 | |
| 126 | |
| 127 | |
| 128 | |
| 129 | |
| 130 | |
| 131 | |
| 132 | |
| 133 | |
| 134 | |
| 135 | |
| 136 | |
| 137 | |
| 138 | |
| 139 | |
| 140 | |
| 141 | |
| 142 | |
| 143 | |
| 144 | |
| 145 | |
| 146 | |
| 147 | |
| 148 | |
| 149 | |
| 150 | |
| 151 | -- |
| 152 | Scott K. Frost INET: scott.frost@cas.org |
| 153 | |
| 154 | |