Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Use tcl to perform linux commands

502 views
Skip to first unread message

Lim Y Hao, Ryan

unread,
Nov 17, 2009, 10:11:04 PM11/17/09
to
I'm a beginner to tcl. Could anyone please answer me the question:
How to use tcl to perform linux commands? What i mean is I want to
write a tcl script that once executed it's able to lets say perfoms
linux commands like:
mkdir temp
mv file1 file2

And then catch the result on the command line into a file.

I have looked at the exec/open commands but they seem to open a file
rather than invoke linux commands. enlighten me pls.

I need this urgently. Any help is appreciated.

Hai Vu

unread,
Nov 17, 2009, 11:38:05 PM11/17/09
to

Please look up the 'file' command such as file mkdir, file rename, ...

bs

unread,
Nov 18, 2009, 12:16:26 AM11/18/09
to
On Nov 17, 7:11 pm, "Lim Y Hao, Ryan" <ryanlim0...@gmail.com> wrote:

exec/open do more than open files. I would look at the wiki for more
details:

http://wiki.tcl.tk/1039
http://wiki.tcl.tk/1241

Also, check to see if there is already a built-in command (as Hai Vu
suggested) first, before using exec and open. Also check tcllib.

Larry W. Virden

unread,
Nov 18, 2009, 7:44:51 AM11/18/09
to
On Nov 17, 10:11 pm, "Lim Y Hao, Ryan" <ryanlim0...@gmail.com> wrote:

> How to use tcl to perform linux commands?

Well, to actually perform the commands, there are at least 2 methods -
the exec command or Tcl's ability to open a pipe to a command (read
the open man page).

>What i mean is I want to
> write a tcl script that once executed it's able to lets say perfoms
> linux commands like:
>       mkdir temp
>       mv file1 file2
>
> And then catch the result on the command line into a file.

You would want to use a Tcl command like gets to get your input, write
the text of the command out to your file, invoke a pipe that routes
the stdout back to your tcl command, then write the output out to your
file.

>
> I have looked at the exec/open commands but they seem to open a file
> rather than invoke linux commands. enlighten me pls.
>


In the reference information for open < http://wiki.tcl.tk/open > ,
read about "COMMAND PIPELINES".

Be sure to read up on handing both stdout AND stderr, so that you
handle the case where the command you execute fails.

Also, don't forget to fflush the output to the file after each write,
so that in case of a crash, as much output as possible is in your log
file.

Neil Madden

unread,
Nov 18, 2009, 10:05:48 AM11/18/09
to

As others have mentioned, these kinds of tasks can be accomplished in
pure Tcl via [file mkdir] and [file rename]. If you really want to do
exactly what you asked for, then something like the following:

exec mkdir temp >>& mylog.txt
exec mv file1 file2 >>& mylog.txt

-- Neil

Lim Y Hao, Ryan

unread,
Nov 18, 2009, 10:38:23 PM11/18/09
to

Thank you very much for your reply.

those mkdir and mv command I stated above are just examples I wanted
to do in linux. Infact I want to use some Iperf commands.
I found out how to do it using exec and open. Now I face another
problems.
Since I use the iperl commands in a loop and each command takes some
times to complete. Hence I need to use the & symbol after each
command to make to execute in parallel and then log the result into a
log file. But the results are displayed on the screen (command line)
and not get logged. Some weird number are logged instead.

Here is the code:
-------------------------------------------------------------------------------
if [catch {open ./log.txt w} io ] {puts "Problem in creating/opening a
file"}
for {set i 1} {$i<5} {incr i} {
put $io [exec iperf -c 192.1.1.1 -B 192.1.1.2$i &]
}
close $io
-------------------------------------------------------------------------------

And the log file log.txt:
3245
1235
1456
2541

Do you know how to tackle this: log all the results on the screen to
the log file log.txt. I think the problem lie on the & symbol. But I
need to execute commands all together at once.

Does the coding style (the way creating log file) is appropriate for
this purpose?

Thank you very much

Lim Y Hao, Ryan

unread,
Nov 18, 2009, 11:05:34 PM11/18/09
to
On Nov 18, 11:05 pm, Neil Madden <n...@cs.nott.ac.uk> wrote:

Thank you very much for your reply.

Donald Arseneau

unread,
Nov 19, 2009, 1:42:34 AM11/19/09
to
On Nov 18, 7:38 pm, "Lim Y Hao, Ryan" <ryanlim0...@gmail.com> wrote:

> Since I use the iperl commands in a loop and each command takes some
> times to complete. Hence I need to use the & symbol after each
> command to make to execute in parallel and then log the result into a
> log file. But the results are displayed on the screen (command line)
> and not get logged. Some weird number are logged instead.
>

> put $io [exec iperf -c 192.1.1.1 -B 192.1.1.2$i &]}

When you think about it, it is bovious that Tcl can *either*
launch the program without waiting *or* wait for its output, but
not both. What exec returns immediately is the process id number
of the detached command. (You can refer to those if you want to
check whether the process has completed.)

What you want is to pipe the output directly to the file without
returning it to the Tcl script:

# Start fresh:
file delete ./log.txt
#


for {set i 1} {$i<5} {incr i} {

exec iperf -c 192.1.1.1 -B 192.1.1.2$i >> ./log.txt &
}

This may or may not give you problems due to output from
different concurrent executions getting mixed together,
depending on the size and form of the output, on the os
file handling, and on my blissful ignorance.

Donald Arseneau

Larry W. Virden

unread,
Nov 19, 2009, 7:26:58 AM11/19/09
to


And in fact, it is highly likely that it will in fact give you the
problems Donald mentioned. You don't normally want to have multiple
processes appending to the same log file unless a) every line of
output from the processes is uniquely identified, so that you can tell
which line came from which command, and b) every process guarantees
that its output will appear as a complete line.

I've seen cases where 2 or more processes writing to the same file had
bits of output intermingled so that you couldn't even tell what came
from where.

What you might want to do is to have each process write out to its own
file, then, once all the processes finish, run a command to
concatenate all the process log files into one master log.


Cyan

unread,
Nov 19, 2009, 11:39:12 AM11/19/09
to

I use something like the following quite a lot, to run several things
in the background, without waiting for them to complete, but still
capturing the output (the example uses tcl8.6isms):


proc run {args} {
set cmd $args
lappend cmd 2>@1
set handle [open |$cmd r]
chan configure $handle -blocking 0
chan event $handle readable [list [info coroutine] output]
set afterid [after 30000 [list [info coroutine] timeout]]
set output ""

try {
while {1} {
lassign [yield] wakeup_reason
switch -- $wakeup_reason {
timeout {
puts "Got bored waiting for [pid $handle]"
throw close ""
}

output {
set chunk [chan read $handle]
if {[chan eof $handle]} {
throw close ""
}
append output $chunk
}
}
}
} trap close {} {
try {
chan configure $handle -blocking 1
chan close $handle
} trap {CHILDSTATUS} {errmsg options} {
lassign [dict get $options -errorcode] - pid code
puts "Child died with exit code $code"
} trap {CHILDKILLED} {errmsg options} {
lassign [dict get $options -errorcode] - pid sigName msg
puts "Child was killed with signal $sigName"
} on ok {} {
puts "Child died naturally, output:\n$output"
}
} finally {
after cancel $afterid
}
}

coroutine coro_[incr ::coroseq] run find /

# Do other stuff
puts "hello, world"

vwait ::forever


Sorry, ended up being more code than I expected

Cyan

Donald Arseneau

unread,
Nov 19, 2009, 11:35:37 PM11/19/09
to
On Nov 19, 4:26 am, "Larry W. Virden" <lvir...@gmail.com> wrote:
> On Nov 19, 1:42 am, Donald Arseneau <a...@triumf.ca> wrote:
> > This may or may not give you problems due to output from
> > different concurrent executions getting mixed together,
>
> And in fact, it is highly likely that it will in fact give you the
> problems Donald mentioned. You don't normally want to have multiple
> processes appending to the same log file unless a) every line of
> output from the processes is uniquely identified, so that you can tell
> which line came from which command, and b) every process guarantees
> that its output will appear as a complete line.

Agreed, and I should have reiterated your instructions to learn
about command pipelines. The project can be accomplished using
[open "|..."] instead of [exec ...] for the launching and [fileevent]
for the collection of output. Then Tcl can write out the log
file in well-separated chunks.

Donald Arseneau

0 new messages