FAQ
hi, im trying to implment a more streamlined way of calling shell commands.

i've come up with the following implementation, which deadlocks on me
(never mind the fact that for the moment, it only runs "ls -al")

i'd appreciate any suggestions or alternative implementations.

i've also made a playground, but it doesn't run since shelling out is not
available (http://play.golang.org/p/qIsx_DCELa)

package main



import (

"bufio"

"io"

"log"

"os/exec"

)

func shell(outChan chan string) {
txt := "ls -al"

cmd := exec.Command("/bin/sh", "-c", txt)

out, err := cmd.StdoutPipe()

if err != nil {

log.Fatalf("Unable to stdoutpipe %s: %s", txt, err)

}

rd := bufio.NewReader(out)
if err := cmd.Start(); err != nil {
log.Fatal("Unable to start command: ", err)

}

for {
line, err := rd.ReadString('\n')

if err == io.EOF && len(line) == 0 {

// Good end of file with no partial line

break

}

if err == io.EOF {

log.Fatal("Last line not terminated: ", err)

}

line = line[:len(line)-1] // drop the '\n'

if line[len(line)-1] == '\r' {

line = line[:len(line)-1] // drop the '\r'

}

go func() {
outChan <- line

}()

}
// Wait for the result of the command; also closes our end of the pipe
err = cmd.Wait()

if err != nil {

log.Fatal("Unable to wait for process to finish: ", err)

}

}

func main() {
out := make(chan string)

shell(out)

for line := range out {

log.Println(line)

}

}




--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Jan Mercl at Jul 10, 2014 at 9:23 am
    On Thu, Jul 10, 2014 at 11:13 AM, wrote:

    - The channel must be buffered.
    - No one is closing the channel.

    -j

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tomwilde at Jul 10, 2014 at 10:27 am
    To elaborate:

    for {
         // ...
         go func() {
             outChan <- line
         }()
    }

    if you care about the order of the lines you shouldn't do this. This will
    schedule various goroutines with different lines to send down the
    unbuffered channel whenever they can. Since these goroutines won't execute
    in scheduling order, the lines will be sent out of order.

    One way of solving this is using a buffered channel in order to "read
    ahead" a number of lines from the console and send them down the channel
    without blocking.

    The other problem is that you are ranging over a channel that never closes
    -- this will result in an endless loop. You must close the channel at some
    point for the range-loop to end.

    - Tom
    On Thursday, July 10, 2014 11:23:50 AM UTC+2, Jan Mercl wrote:

    On Thu, Jul 10, 2014 at 11:13 AM, <lbor...@gmail.com <javascript:>>
    wrote:

    - The channel must be buffered.
    - No one is closing the channel.

    -j
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Lboregard at Jul 10, 2014 at 11:23 am
    thank you Jan Merci and tomwilde.
    On Thursday, July 10, 2014 5:27:31 AM UTC-5, tomwilde wrote:

    To elaborate:

    for {
    // ...
    go func() {
    outChan <- line
    }()
    }

    if you care about the order of the lines you shouldn't do this. This will
    schedule various goroutines with different lines to send down the
    unbuffered channel whenever they can. Since these goroutines won't execute
    in scheduling order, the lines will be sent out of order.

    One way of solving this is using a buffered channel in order to "read
    ahead" a number of lines from the console and send them down the channel
    without blocking.

    The other problem is that you are ranging over a channel that never closes
    -- this will result in an endless loop. You must close the channel at some
    point for the range-loop to end.

    - Tom
    On Thursday, July 10, 2014 11:23:50 AM UTC+2, Jan Mercl wrote:

    On Thu, Jul 10, 2014 at 11:13 AM, wrote:

    - The channel must be buffered.
    - No one is closing the channel.

    -j
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Shawn Milochik at Jul 10, 2014 at 1:57 pm

    On Thu, Jul 10, 2014 at 6:27 AM, tomwilde wrote:

    To elaborate:

    for {
    // ...
    go func() {
    outChan <- line
    }()
    }

    Isn't that example succeptible to this?
    https://code.google.com/p/go-wiki/wiki/CommonMistakes

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tomwilde at Jul 10, 2014 at 2:43 pm
    No, because line is defined inside the loop.
    On Thursday, July 10, 2014 3:57:56 PM UTC+2, Shawn Milochik wrote:

    On Thu, Jul 10, 2014 at 6:27 AM, tomwilde <sedevel...@gmail.com
    <javascript:>> wrote:
    To elaborate:

    for {
    // ...
    go func() {
    outChan <- line
    }()
    }

    Isn't that example succeptible to this?
    https://code.google.com/p/go-wiki/wiki/CommonMistakes
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Gustavo Niemeyer at Jul 10, 2014 at 11:30 am
    This might help with the underlying goal: http://labix.org/pipe
    On Thu, Jul 10, 2014 at 6:13 AM, wrote:
    hi, im trying to implment a more streamlined way of calling shell commands.

    i've come up with the following implementation, which deadlocks on me (never
    mind the fact that for the moment, it only runs "ls -al")

    i'd appreciate any suggestions or alternative implementations.

    i've also made a playground, but it doesn't run since shelling out is not
    available (http://play.golang.org/p/qIsx_DCELa)
    package main



    import (

    "bufio"

    "io"

    "log"

    "os/exec"

    )


    func shell(outChan chan string) {

    txt := "ls -al"

    cmd := exec.Command("/bin/sh", "-c", txt)

    out, err := cmd.StdoutPipe()

    if err != nil {

    log.Fatalf("Unable to stdoutpipe %s: %s", txt, err)

    }


    rd := bufio.NewReader(out)


    if err := cmd.Start(); err != nil {

    log.Fatal("Unable to start command: ", err)

    }


    for {

    line, err := rd.ReadString('\n')

    if err == io.EOF && len(line) == 0 {

    // Good end of file with no partial line

    break

    }

    if err == io.EOF {

    log.Fatal("Last line not terminated: ", err)

    }

    line = line[:len(line)-1] // drop the '\n'

    if line[len(line)-1] == '\r' {

    line = line[:len(line)-1] // drop the '\r'

    }


    go func() {

    outChan <- line

    }()


    }


    // Wait for the result of the command; also closes our end of the pipe

    err = cmd.Wait()

    if err != nil {

    log.Fatal("Unable to wait for process to finish: ", err)

    }

    }


    func main() {

    out := make(chan string)

    shell(out)

    for line := range out {

    log.Println(line)

    }

    }

    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.


    --

    gustavo @ http://niemeyer.net

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedJul 10, '14 at 9:13a
activeJul 10, '14 at 2:43p
posts7
users5
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase