Question about Process output

Hello, I would like when the software I’m coding launch a process visible in the terminal, to as well write this output in a file (to trace everything, so a log).

For example with this process:

tasks = <<-CODE
                                    require "./RequiredLibraries"
                                    Ism = ISM::CommandLine.new
                                    Ism.loadSoftwareDatabase
                                    Ism.loadSettingsFiles
                                    require "./#{requirePath}"
                                    target = Target.new("#{targetPath}")

                                    begin
                                        target.download
                                        target.check
                                        target.extract
                                        target.patch
                                        target.prepare
                                        target.configure
                                        target.build
                                        target.prepareInstallation
                                        target.install
                                        target.clean
                                    rescue
                                        exit 1
                                    end

                                    CODE

                                    File.write("ISM.task", tasks)

                                    process = Process.run("crystal",args: ["ISM.task"],output: :inherit,error: :inherit,)

                                    if !process.success?
                                        break
                                    end

I guess following is what you want?

STDOUT.reopen(log_path); STDOUT.sync = true

If you just want to write to multiple IOs, you could prob just use IO::MultiWriter - Crystal 1.6.2. Where one is STDOUT then another is a reference to a File instance.

1 Like

Sorry I’m a bit lost. I didn’t use a lot STDOUT.

I tried both of the solution, but I have just an empty file. I did something wrong ?

require "file_utils"

FileUtils.touch("log.txt")

file = File.new("log.txt")

process = Process.run("ping",args: ["www.google.fr"], output: :inherit,
                                            error: :inherit,
                                            shell: true)

writer = IO::MultiWriter.new(file)
writer.puts process
require "file_utils"

FileUtils.touch("log.txt")

file = File.new("log.txt")

process = Process.run("ping",args: ["www.google.fr"], output: :inherit,
                                            error: :inherit,
                                            shell: true)

STDOUT.reopen(file); STDOUT.sync = true

Blacksmoke16 answer is the correct answer, following code works for me.

file = File.open("log.txt", "w")

io1 = STDOUT
io2 = file

writer = IO::MultiWriter.new(io1, io2)

process = Process.run(
  "ping www.google.fr-c 5",
  output: writer,
  error: writer,
  shell: true
)

file.close

Another way is save output into memory, then puts it in different place if necessary.

stdout = IO::Memory.new
stderr = IO::Memory.new

process = Process.run(
  "ping www.baidu.com -c 5",
  output: stdout,
  error: stderr,
  shell: true
)

if process.success?
  STDOUT.puts stdout.to_s
  File.open("log.txt", "w") do |file|
    file.puts stdout.to_s
  end
end

Thanks you I will apply that to my project. Just one question: How IO::MultiWriter stop, when the process end or break ?

Is it possible to stop (just in case I need) to stop the MultiWriter before the end of the process ?

I guess as well I can use only one MultiWriter, I don’t need to make a new MultiWriter for each process ?

How IO::MultiWriter stop, when the process end or break ?

IO::MultiWriter#close will do the trick? there is a sync_close option, probably involves.

I guess as well I can use only one MultiWriter, I don’t need to make a new MultiWriter for each process ?

I don’t know, base on your’s use context ?

1 Like

Thank you very much for your help zw963, now with the logs I generated, I was able to solve my last problems I had with my software. Now it able to build the crosstoolchain and temporary tools steps from the LFS, and the chroot work. Thanks so much !

2 Likes

I have an another question in my mind. Is it possible to have the error output (like with :inherit) and as well saved in a String ?

Because if I convert with .to_s, this add quote in the string.

Make one of your IOs you’re passing to the multi writer an IO::Memory. That’ll give you an in memory string representation of what was output via the command.