Output redirection to exec does not work

Hello Experts,

I am on Solaris 10

Due to some limitations in one of the vendor software, I am forced to output the command to exec and then run it from there.

For example..

$(echo "/usr/bin/cp a.dat b.dat") # This works

However,

$(echo "/usr/bin/cat a.dat > c.dat") # This does not work

Are are any ways to workaround this problem..

The error I get is

cat: cannot open >
cat: cannot open c.dat

Rgds,
Gokul

Hi.

I'm not quite sure what you are trying to do, or what you mean by "some limitations in one of the vendor software", when this looks like a shell script.

This won't work:

$(echo "/usr/bin/cat a.dat > c.dat")

But this will:

$(echo "/usr/bin/cat a.dat" > c.dat)

Could you please elaborate?

1 Like

Thanks for your response.

The vendor software provides an option to execute Unix commands from the user interface, but for some reason commands that involve redirections doesn't seem to work from that interface. That is what I meant by vendor software limitation.

Rgds,
Gokul

---------- Post updated at 07:12 PM ---------- Previous update was at 07:06 PM ----------

$(echo "/usr/bin/cat a.dat > " c.dat) doesn't work..I get the following error.

cat: cannot open >
cat: cannot open c.dat

Rgds,
Gokul

Hi.

If the "vendor software" allows you to execute unix commands from the user interface, did you try just:

/usr/bin/cat a.dat > c.dat

? (i.e. why use $(...)?)

Having no idea where this "vendor software" might chose to write c.dat, you might want to fully qualify a path to c.dat.

In any case the command you quoted:

$(echo "/usr/bin/cat a.dat > " c.dat)

is not the one I wrote:

$(echo "/usr/bin/cat a.dat" > c.dat)

If you're still having problems, perhaps you could explain more about this "vendor sorfware" (i.e. is it UNIX-based, Windows-based, Web-based, based on some remote server, etc.)

Actually, I have tried all those options. Like you mention, the vendor software works fine with commands that doesnt involve redirections But the software can execute a script. I am in a situation not to create any news scripts in production and would like to make use of the command execution features.

I was trying to create a script, that can accept commands as an argument and execute them...

cat > a.sh
#!/bin/ksh
$1

For example, passing an argument like "cat a.dat > c.dat" does not work.

But, this does not work for commands with redirections. If the problem with the script can be solved, I think my problem will be solved as well..

Rgds,
Gokul

That's because by the time the redirection character is seen, the shell parser has already passed the stage where it's looking for redirections. You need to use eval to pass the expansion through the parser a second time. This is error prone on all but trivial commands. Read up on the eval built-in, if you're interested in pursuing it.

In the following, ">" is treated as just another character:

$ $(echo "echo hello  > stdout")
hello > stdout
$ cat stdout
cat: stdout: No such file or directory

Here, "echo hello > stdout" is sent through the sh parser and ">" is seen by the redirection step:

$ eval $(echo "echo hello  > stdout")
$ cat stdout 
hello

In your example, you can try:

#!/bin/ksh
eval "$1"

Proceed with caution. Caveat admin.

Regards,
Alister

Thanks for your response. From the truss output, I see the command is passed to the execve function. In both cases I see errors in the truss output.

"/usr/bin/cat /opt/CMT/partitions/partition1/a.txt > /opt/CMT/partitions/partition1/b.txt"

/opt/CMT/partitions/partition1$ls /usr/bin/cat
/usr/bin/cat

/opt/CMT/partitions/partition1$ls /opt/CMT/partitions/partition1/a.txt
/opt/CMT/partitions/partition1/a.txt

Truss
--------
28573:  getuid()                                        = 930549 [930549]
28573:  execve("/usr/bin/cat /opt/CMT/partitions/partition1/a.txt > /opt/CMT/partitions/partition1/b.txt", 0x100D02090, 0xFFFFFFFF7FFFFB08) Err#2 ENOENT
28573:  _exit(2)
8231/8:         open("/opt/CMT/partitions/partition1/logs/ContactLog.log", O_RDWR|O_APPEND|O_CREAT|O_LARGEFILE, 0666) = 17
8231/8:         fstat(17, 0xFFFFFFFF76DFEFB8)                   = 0
8231/8:         lseek(17, 0, SEEK_CUR)                          = 0


/usr/bin/cat /opt/CMT/partitions/partition1/a.txt > /opt/CMT/partitions/partition1/t.txt

Truss
-----
6320:   execve("/usr/bin/cat", 0x100E29790, 0xFFFFFFFF7FFFFB08)  argc = 4
6320:   resolvepath("/usr/lib/ld.so.1", "/lib/ld.so.1", 1023) = 12
6320:   resolvepath("/usr/bin/cat", "/usr/bin/cat", 1023) = 12
6320:   stat64("/usr/bin/cat", 0xFFBFF8B0)              = 0
6320:   open("/var/ld/ld.config", O_RDONLY)             Err#2 ENOENT
6320:   stat64("/opt/CMT/bin/libc.so.1", 0xFFBFF040) Err#2 ENOENT
6320:   stat64("/opt/oracle/product/10.2.0.3/lib/libc.so.1", 0xFFBFF040) Err#2 ENOENT
6320:   stat64("/opt/teradatav2r6/odbc64/lib/libc.so.1", 0xFFBFF040) Err#2 ENOENT
6320:   stat64("/opt/teradatav2r6/lib64/libc.so.1", 0xFFBFF040) Err#2 ENOENT
6320:   stat64("/lib/libc.so.1", 0xFFBFF040)            = 0
6320:   resolvepath("/lib/libc.so.1", "/lib/libc.so.1", 1023) = 14
6320:   open("/lib/libc.so.1", O_RDONLY)                = 3
6320:   mmap(0x00010000, 32768, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_ALIGN, 3, 0) = 0xFF3A0000
6320:   mmap(0x00010000, 1294336, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE|MAP_ANON|MAP_ALIGN, -1, 0) = 0xFF200000
6320:   mmap(0xFF200000, 1237333, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_TEXT, 3, 0) = 0xFF200000
6320:   mmap(0xFF330000, 35645, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_INITDATA, 3, 1245184) =
6320:   mmap(0xFF33A000, 1416, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANON, -1, 0) = 0xFF33A00
6320:   memcntl(0xFF200000, 145120, MC_ADVISE, MADV_WILLNEED, 0, 0) = 0
6320:   close(3)                                        = 0
6320:   mmap(0x00010000, 24576, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON|MAP_ALIGN, -1, 0) = 0xFF3900
6320:   munmap(0xFF3A0000, 32768)                       = 0
6320:   getcontext(0xFFBFF720)
6320:   getrlimit(RLIMIT_STACK, 0xFFBFF700)             = 0
6320:   getpid()                                        = 6320 [867]
6320:   setustack(0xFF392A88)
6320:   mmap(0x00000000, 8192, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0) = 0xFF3F0000
6320:   brk(0x0002A600)                                 = 0
6320:   brk(0x0002C600)                                 = 0
6320:   stat64("/platform/SUNW,Sun-Fire-15000/lib/libc_psr.so.1", 0xFFBFE670) = 0
6320:   resolvepath("/platform/SUNW,Sun-Fire-15000/lib/libc_psr.so.1", "/platform/sun4u-us3/lib/libc_psr.so.1", 1
6320:   open("/platform/SUNW,Sun-Fire-15000/lib/libc_psr.so.1", O_RDONLY) = 3
6320:   mmap(0x00010000, 32768, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_ALIGN, 3, 0) = 0xFF3A0000
6320:   munmap(0xFF3A2000, 24576)                       = 0
6320:   close(3)                                        = 0
6320:   stat64("/usr/lib/locale/en_US/en_US.so.3", 0xFFBFE7F8) = 0
6320:   resolvepath("/usr/lib/locale/en_US/en_US.so.3", "/usr/lib/locale/en_US.ISO8859-1/en_US.ISO8859-1.so.3", 1
6320:   open("/usr/lib/locale/en_US/en_US.so.3", O_RDONLY) = 3
6320:   mmap(0x00010000, 32768, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_ALIGN, 3, 0) = 0xFF380000
6320:   mmap(0x00010000, 90112, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE|MAP_ANON|MAP_ALIGN, -1, 0) = 0xFF360000
6320:   mmap(0xFF360000, 16093, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_TEXT, 3, 0) = 0xFF360000
6320:   mmap(0xFF372000, 10158, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_INITDATA, 3, 8192) = 0x
6320:   munmap(0xFF364000, 57344)                       = 0
6320:   memcntl(0xFF360000, 6624, MC_ADVISE, MADV_WILLNEED, 0, 0) = 0
6320:   close(3)                                        = 0
6320:   stat64("/opt/CMT/bin/libc.so.1", 0xFFBFE6C8) Err#2 ENOENT
6320:   stat64("/opt/oracle/product/10.2.0.3/lib/libc.so.1", 0xFFBFE6C8) Err#2 ENOENT
6320:   stat64("/opt/teradatav2r6/odbc64/lib/libc.so.1", 0xFFBFE6C8) Err#2 ENOENT
6320:   stat64("/opt/teradatav2r6/lib64/libc.so.1", 0xFFBFE6C8) Err#2 ENOENT
6320:   munmap(0xFF380000, 32768)                       = 0
6320:   fstat64(1, 0xFFBFFAF8)                          = 0
6320:   open64("/opt/CMT/partitions/partition1/a.txt", O_RDONLY) = 3
6320:   fstat64(3, 0xFFBFFA60)                          = 0
6320:   llseek(3, 0, SEEK_CUR)                          = 0
6320:   read(3, " S D K F S D F K D S F K".., 8192)     = 94
6320:   write(1, " S D K F S D F K D S F K".., 94)      Err#5 EIO
6320:   open("/usr/lib/locale/en_US/LC_MESSAGES/SUNW_OST_OSCMD.mo", O_RDONLY) Err#2 ENOENT
6320:   fstat64(2, 0xFFBFEAA0)                          = 0
6320:   write(2, " c a t :   o u t p u t  ".., 19)      Err#5 EIO
6320:   open("/usr/lib/locale/en_US/LC_MESSAGES/SUNW_OST_OSLIB.mo", O_RDONLY) Err#2 ENOENT
6320:   write(2, " I / O   e r r o r", 9)               Err#5 EIO
6320:   write(2, "\n", 1)                               Err#5 EIO
6320:   llseek(3, 0, SEEK_CUR)                          = 94
6320:   close(3)                                        = 0
6320:   open64(">", O_RDONLY)                           Err#2 ENOENT
6320:   write(2, " c a t :   c a n n o t  ".., 17)      Err#5 EIO
6320:   open64("/opt/CMT/partitions/partition1/t.txt", O_RDONLY) = 3
6320:   fstat64(3, 0xFFBFFA60)                          = 0
6320:   llseek(3, 0, SEEK_CUR)                          = 0
6320:   read(3, 0x000222A0, 8192)                       = 0
6320:   llseek(3, 0, SEEK_CUR)                          = 0
6320:   close(3)                                        = 0
6320:   close(1)                                        = 0
6320:   _exit(2)

I cannot use eval as the path for eval does not exist. Is there any other alternative to trick the execve function to execute commands with redirections ?

Rgds,
Gokul

So it's not a vendor limitation as much as an execve limitation. You're not given a shell at all, so no shell commands will operate, including redirection. You could run your own shell:

/bin/sh -c "echo a > b"

Amazing..that one worked really well. Many thanks..

Apologies for not being clear initially..

Rgds,
Gokul