How do retrieve output from a bashscript that you run from a tcl script <- (modulefile script)

273 Views Asked by At

In my home dir, I have sub directories (CentOS, Ubuntu, etc) all for specific nodes I have access to.

  • Each OS will hold their own copy of programs, one of which is Python:

    $HOME/{CentOS, Ubuntu, ...}/{python2,python3}
    
  • I am using environment modules so that when I ssh into a different computer (COMP), Python aliases will be set for that specific (COMP). For example:

    1. COMP1 is CentOS

      when I ssh into COMP1, "python3" should point to $HOME/Centos/python3/bin/python3

    2. COMP2 is Ubuntu

      when I ssh into COMP2 "python2" should point to $HOME/Ubuntu/python2/bin/python2


I can retrieve the OS name in bash using lsb_release -si, but I am working with modulefiles which are written in tcl, and haven't found something like lsb_release. Can I have a bash script that outputs lsb_release -si when called from a tcl script?

  • I tried doing this but no luck:

    BASH SCRIPT:

    #!/bin/bash
    
    OS=$(lsb_release -si)
    echo $OS
    

MODULEFILE SCRIPT:

#%Modulefile1.0

set OS [catch {exec bash /path/to/bash_file} output]
puts $OS

This doesn't do much.

2

There are 2 best solutions below

0
On

Option A: export the variable in bash and access the environment variable in tcl.

#!/bin/bash
OS=$(lsb_release -si)
export OS
somescript.tcl

#!/usr/bin/tclsh
puts $::env(OS)

Option B: Use the platform package that comes with tcl.

#!/usr/bin/tclsh
package require platform
puts [platform::identify] ; # detailed OS-CPU
puts [platform::generic] ; # more generic OS-CPU

References: env platform

0
On

Your code mostly doesn't look obviously wrong.

But following the [catch {exec ...} output] the value that you are looking for should be in the output variable; the OS variable will have a code indicating effectively whether the bash script produced any output to stderr. Since you're definitely not interested in that debugging output which might be produced for reasons not under your easy control, you can probably do this:

catch {exec bash /path/to/bash_file 2>/dev/null} output
puts $output

Also make sure your bash script has an explicit exit at the end. Might as well ensure that it stops correctly. That's the default behaviour, but it's better to be explicit here as this is a (small) program.