I am working with Pharo 3 and I use the Transcript to record operations.
However the size of the current buffer is short for my needs. How to increase it? There is characterLimit but this is a method constant and therefore not easy to set up without changing a core package.
I do not want to use NonInteractiveTranscript because I want to stay in the image.
No, there is no other way to change the buffer length of the Transcript then to modify #characterLimit (usually of ThreadSafeTranscript). However, try inspecting ThreadSafeTranscript allInstances and you'll see that the underlying stream is much longer (50000 something is the write limit there). So, whatever you're printing to Transcript is not actually lost but just not visible.
That being said, using Transcript for extensive output is generally not a good idea because:
output is cut off (as you've already seen)
Transcript is really slow when called repeatedly:
try
1 to: 10000 do: [ :i | Transcript show: i ]
vs.
Transcript show: (String streamContents: [ :stream |
1 to: 10000 do: [ :i | stream nextPutAll: i asString ] ])
you can't use the output somewhere else (e.g. to write to file or pass along to a method)
In my opinion Transcript is ok for occasional quick debugging but shouldn't be used for anything application related.
Related
I have a problem with ksh in that a while loop is failing to obey the "while" condition. I should add now that this is ksh88 on my client's Solaris box. (That's a separate problem that can't be addressed in this forum. ;) I have seen Lance's question and some similar but none that I have found seem to address this. (Disclaimer: NO I haven't looked at every ksh question in this forum)
Here's a very cut down piece of code that replicates the problem:
1 #!/usr/bin/ksh
2 #
3 go=1
4 set -x
5 tail -0f loop-test.txt | while [[ $go -eq 1 ]]
6 do
7 read lbuff
8 set $lbuff
9 nwords=$#
10 printf "Line has %d words <%s>\n" $nwords "${lbuff}"
11 if [[ "${lbuff}" = "0" ]]
12 then
13 printf "Line consists of %s; time to absquatulate\n" $lbuff
14 go=0 # Violate the WHILE condition to get out of loop
15 fi
16 done
17 printf "\nLooks like I've fallen out of the loop\n"
18 exit 0
The way I test this is:
Run loop-test.sh in background mode
In a different window I run commands like "echo some nonsense >>loop_test.txt" (w/o the quotes, of course)
When I wish to exit, I type "echo 0 >>loop-test.txt"
What happens? It indeed sets go=0 and displays the line:
Line consists of 0; time to absquatulate
but does not exit the loop. To break out I append one more line to the txt file. The loop does NOT process that line and just falls out of the loop, issuing that "fallen out" message before exiting.
What's going on with this? I don't want to use "break" because in the actual script, the loop is monitoring the log of a database engine and the flag is set when it sees messages that the engine is shutting down. The actual script must still process those final lines before exiting.
Open to ideas, anyone?
Thanks much!
-- J.
OK, that flopped pretty quick. After reading a few other posts, I found an answer given by dogbane that sidesteps my entire pipe-to-while scheme. His is the second answer to a question (from 2013) where I see neeraj is using the same scheme I'm using.
What was wrong? The pipe-to-while has always worked for input that will end, like a file or a command with a distinct end to its output. However, from a tail command, there is no distinct EOF. Hence, the while-in-a-subshell doesn't know when to terminate.
Dogbane's solution: Don't use a pipe. Applying his logic to my situation, the basic loop is:
while read line
do
# put loop body here
done < <(tail -0f ${logfile})
No subshell, no problem.
Caveat about that syntax: There must be a space between the two < operators; otherwise it looks like a HEREIS document with bad syntax.
Er, one more catch: The syntax did not work in ksh, not even in the mksh (under cygwin) which emulates ksh93. But it did work in bash. So my boss is gonna have a good laugh at me, 'cause he knows I dislike bash.
So thanks MUCH, dogbane.
-- J
After articulating the problem and sleeping on it, the reason for the described behavior came to me: After setting go=0, the control flow of the loop still depends on another line of data coming in from STDIN via that pipe.
And now that I have realized the cause of the weirdness, I can speculate on an alternative way of reading from the stream. For the moment I am thinking of the following solution:
Open the input file as STDIN (Need to research the exec syntax for that)
When the condition occurs, close STDIN (Again, need to research the syntax for that)
It should then be safe to use the more intuitive:while read lbuffat the top of the loop.
I'll test this out today and post the result. I'd hope someone else benefit from the method (if it works).
Smalltalk inspect is a powerful tool. Is there any (easy) way to get the information from inspect and show it in Transcript window or write into a file instead of showing it in new window?
I need it because I want to create a kind of debbuger for a program that runs as unix process (not a 'window' program) and logs information into a log file.
Thanks for help!
If you're asking whether something is built in, then I don't think so (although it would help if you tagged the question with which Smalltalk you are using).
Although it would be pretty easy to walk over the inst vars and roll your own (although maybe not for immediate objects), the "easiest" way might be to look at the inspector code and see how it operates. For example, in Pharo 4.0 one could (very basically) leverage the inspector code like so:
i := EyeInspector inspector: 1.
Transcript show: i objectClass; cr.
i elements do: [ :e | Transcript show: e; cr ].
which would print:
SmallInteger
'self'->1
'hex'->1
'octal'->1
'binary'->1
'character'->Character home
In Pharo, you can also get all of the Transcript output going to the console with:
NonInteractiveTranscript stdout install
If you are about debugging, you can have debugger interactions dump things into files (of course, you'll not be able to step in there but it can be useful for headless systems):
NonInteractiveUIManager compile: 'openDebuggerOn: process context: context label: title contents: contentsStringOrNil fullView: bool
| out |
out := VTermOutputDriver stdout.
out
<< ''NonInteractive Debugger: '';
<< title;
cr.
contentsStringOrNil ifNotNil: [ out << contentsStringOrNil; cr ].
(context stackOfSize: 20) do: [:s | out << s printString; cr ].
out << ''------------------------------''; cr; cr.
^ self nonInteractiveWarning: ''Opening Debugger''' classified: #'ui-requests'.
This and Sean's answer should go a long way.
You can get back to normal with the Transcript with:
ThreadSafeTranscript install.
Pharo 3.0 here.
In Rebol, there are words for directory and file management, like make-dir, what-dir, rename, create-link, etc.
But I cannot find a word to simply copy a file to another location or to a newly created file.
A solution is to READ and WRITE. For example, I can do:
>> source: %.bash_history
== %.bash_history
>> target: %nothing
== %nothing
>> write/binary target (read/binary source)
And it works well. But what if I have a file larger than the available memory? Is there any way to copy a file without loading it into memory?
At the moment, I do with a CALL to the underlying OS:
>> call rejoin ["cp " to-string source " " to-string target]
But this is not portable to some different platforms than mine (GNU/Linux Mint): it will run on all Unices, Mac OSX, but not the rest.
I suppose it shouldn't be too hard to write a small function to do this, guessing the running operating system, and adapting the command line accordingly.
So my question: is there already a rebol standard word to copy files? If not, is there a plan to make one, in a module or something?
I don't recall a built-in way to do it aside from what's in the question, but you can do that by using file ports without buffering:
source: open/direct/binary/read %source
target: open/direct/binary/write %target
bytes_per: 1024 * 100
while [not none? data: copy/part source bytes_per][
insert target data
]
close target
close source
(Note: This answer is for Rebol 2)
You can also use system/version to detect which OS your script runs on:
call rejoin either 3 = system/version/4 [
;windows
[{copy "} to-local-file source {" "} to-local-file target {"}]
] [
;others
["cp " to-string source " " to-string target]
]
check this script as well http://www.rebol.org/view-script.r?script=environ.r
If there are other cases you can use;
switch/default system/version/4 [
2 [] ;mac
3 [] ;win
;...
] [
;default
]
Also check there, a few other answers for this problem:
Carl implemented something (I'm surprised it is not included in the heart of Rebol):
http://www.rebol.com/article/0281.html
And Patrick was as surprised as you, a decade and some days ago:
http://www.mail-archive.com/rebol-list#rebol.com/msg16473.html
Here is the simple perl script fetching data from SQL.
Read data and write on a file OUTFILE, and print the data on screen for every 10000th line.
One thing I am curious is that the printing the data on screen terminates very quickly(in 30 seconds), however, data fetching and writing on a file ends very slowly(30 minutes later).
The amount of data is not large. The output files size is less than 100Mbyte.
while ( my ($a,$b) = $curSqlEid->fetchrow_array() )
{
printf OUTFILE ("%s,%d\n", $a,$b);
$counter ++;
if($counter % 10000 == 0){
printf ("%s,%d\n", $a,$b);
}
}
$curSqlEid->finish();
$dbh->disconnect();
close(OUTFILE);
You are suffering from buffering.
Handles other than STDERR are buffered by default, and most handles use a block buffering. That means Perl will wait until there is 8KB* of data to write before sending anything to the system.
STDOUT is special. When is attached to a terminal (and only then), it uses a different kind of buffering: line buffering. When using line buffering, the data is flushed every time a newline is encountered in the data to write.
You can see this by running
$ perl -e'print "abc"; print "def"; sleep 5; print "\n"; sleep 5;'
[ 5 seconds pass ]
abcdef
[ 5 seconds pass ]
$ perl -e'print "abc"; print "def"; sleep 5; print "\n"; sleep 5;' | cat
[ 10 seconds pass ]
abcdef
The solution is to turn off buffering.
use IO::Handle qw( ); # Not needed on Perl 5.14 or later
OUTFILE->autoflush(1);
* — 8KB is the default. It can be configured when Perl is compiled. It used to be a non-configurable 4KB until 5.14.
I think you are seeing the output file size as 0 while the script is running and displaying on the console. Do not go by that. The file size will show up only once the script has finished. This is due to output buffering.
Anyways, the delay cannot be as large as 30 min. Once the script is done, you should see the output file data.
I tried various things, but the final conclusion is that python and perl has basically different handling data flow from DB. It looks like in perl, it is possible to handle data line by line while the data is transferred from DB. However, in Python it needs to wait until the entire data download from the server to process it.
Can I launch Squeak as a REPL (no GUI), where I can enter and evaluate Smalltalk expressions? I know the default image don't allow this. Is there any documentation on how to build a minimum image that can be accessed from a command-line shell?
Here is a (hackish) solution:
First, you need OSProcess, so run this in a Workspace:
Gofer new squeaksource:'OSProcess'; package:'OSProcess';load.
Next, put this in the file repl.st:
OSProcess thisOSProcess stdOut
nextPutAll: 'Welcome to the simple Smalltalk REPL';
nextPut: Character lf; nextPut: $>; flush.
[ |input|
[ input := OSProcess readFromStdIn.
input size > 0 ifTrue: [
OSProcess thisOSProcess stdOut
nextPutAll: ((Compiler evaluate: input) asString;
nextPut: Character lf; nextPut: $>; flush
]
] repeat.
]forkAt: (Processor userBackgroundPriority)
And last, run this command:
squeak -headless path/to/squeak.image /absolute/path/to/repl.st
You can now have fun with a Smalltalk REPL. Dont forget to type in the command:
Smalltalk snapshot:true andQuit:true
if you want to save your changes.
Now, onto the explanation of this solution:
OSProcess is a package that allows to run other processes, read from stdin, and write to stdout and stderr. You can access the stdout AttachableFileStream with OSProcess thisOSProcess (the current process, aka squeak).
Next, you run an infinite loop at userBackgroundPriority (to let other processes run). In this infinite loop, you use Compiler evaluate: to execute the input.
And you run this in a script with a headless image.
As of Pharo 2.0 (and 1.3/1.4 with the fix described below), there are no more hacks necessary. The following snippet will turn your vanilla Pharo image into a REPL server...
From https://gist.github.com/2604215:
"Works out of the box in Pharo 2.0. For prior versions (definitely works in 1.3 and 1.4), first file in https://gist.github.com/2602113"
| command |
[
command := FileStream stdin nextLine.
command ~= 'exit' ] whileTrue: [ | result |
result := Compiler evaluate: command.
FileStream stdout nextPutAll: result asString; lf ].
Smalltalk snapshot: false andQuit: true.
If you want the image to always be a REPL, put the code in a #startup: method; otherwise, pass the script at the command line when you want REPL mode, like:
"/path/to/vm" -headless "/path/to/Pharo-2.0.image" "/path/to/gistfile1.st"
Please visit:
http://map.squeak.org/package/2c3b916b-75e2-455b-b25d-eba1bbc94b84
and Run Smalltalk on server without GUI?
The project http://www.squeaksource.com/SecureSqueak.html includes a REPL package that may provide much of what you are looking for.