0

To check if mdnsd is in probing mode we are using below command to browse for service and redirect its output a file, and hostname of the device is found in the command we decide that mdnsd is in probing mode.

command used for publishing service

dns-sd -R "Test status" "_mytest._tcp." "local." "22"

To browse the service following command is used (Running in background)

dns-sd -lo -Z _mytest._tcp > /tmp/myfile &

To display the content of the file used cat.

cat /tmp/myfile

myfile is empty, if > replaced with tee , I see output on console myfile remains empty.

I am unable to understand what is going on.

Is there any pointer, help

EDIT
Just for completeness adding output, which i missed adding before.

# dns-sd -lo -Z _mytest._tcp local
Using LocalOnly
Using interface -1
Browsing for _mytest._tcp
DATE: ---Tue 25 Apr 2017---
11:09:24.775  ...STARTING...

; To direct clients to browse a different domain, substitute that domain in place of '@'
lb._dns-sd._udp                                 PTR     @

; In the list of services below, the SRV records will typically reference dot-local Multicast DNS names.
; When transferring this zone file data to your unicast DNS server, you'll need to replace those dot-local
; names with the correct fully-qualified (unicast) domain name of the target host offering the service.

_mytest._tcp                                    PTR     Test\032status._mytest._tcp
Test\032status._mytest._tcp                     SRV     0 0 22 DevBoard.local. ; Replace with unicast FQDN of target host
Test\032status._mytest._tcp                     TXT     ""
ART
  • 1,509
  • 3
  • 29
  • 47
  • How are you waiting for the background process to exit, or otherwise ensuring that it does so before you try to read from its output? How are you checking its exit status? How are you capturing any error it emits? – Charles Duffy Apr 24 '17 at 16:19
  • Waiting using `usleep 25000` if I run it with `tee` i see output on console and then check file content and still there file is empty. – ART Apr 24 '17 at 16:29
  • That doesn't actually answer my questions. If you want to check exit status, you should capture the PID, pass it to `wait`, and then check the exit status of that `wait` command. If you want to capture stderr, you should redirect it to a separate file if you don't have any way of capturing it for the whole script. – Charles Duffy Apr 24 '17 at 16:33
  • There are other questions here -- for instance, how frequently is this code running? If it takes 3 seconds to get a response and you're running code that has a redirection `>/tmp/myfile` every second, then you're truncating the file (emptying it out) more often than you're populating it. (This is one of the arguments against reusing fixed temporary file names -- using `mktemp` to generate unique names avoids the entire class of issues). – Charles Duffy Apr 24 '17 at 16:35
  • I would do wait however command `dns-sd -lo -Z _mytest._tcp` doesn't exit. that's the reason command is ran in background. To confirm if issue is because file being open but not flushed out, I sent `SIG_INT` to PID of that process so that it would exit and flush out file, but result is same. Even strange thing is sometime it works. It works on my colleague's board but not on mine and other colleague. – ART Apr 25 '17 at 06:41
  • Response is immediate, this particular command is run from another script, and on failure that command is retried. As response is immediate i don't think issue is because command is run multiple times. – ART Apr 25 '17 at 06:46
  • i tried `script -q -c` to avoid buffering but it didn't help, May be i have to try something else. – ART Apr 25 '17 at 12:00
  • (Have you checked stderr, by the way?) – Charles Duffy Apr 25 '17 at 12:01
  • Yup, no luck either. – ART Apr 25 '17 at 12:02
  • Considered using process substitution instead of messing around with background process and temporary files, by the way? (Oh, n/m, not available in ash). – Charles Duffy Apr 25 '17 at 12:03
  • Is your BusyBox built with the stdbuf command? – Charles Duffy Apr 25 '17 at 12:05
  • no but I can include it and build my busybox. I was also looking at SO post with stdbuf command. I will try that. :) – ART Apr 25 '17 at 12:06
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/142609/discussion-between-charles-duffy-and-ankurtank). – Charles Duffy Apr 25 '17 at 12:14
  • Quick question, by the way -- in the working terminal case, does `2>/dev/null` suppress your output? (Just to be *completely sure* it's stderr, vs stdout) -- if so, you could make it `script -q -f -c 'dns-sd -lo -Z _mytest._tcp local 2>/dev/null'`, and not need to filter out logs like `Using LocalOnly`). – Charles Duffy Apr 25 '17 at 14:52
  • with `dns-sd -lo -Z _mytest._tcp local 2> /dev/null` it displays on the console. So surely its not `stderr`. – ART Apr 25 '17 at 14:54

1 Answers1

1

You appear to have a program with behavior that differs based on whether its output is to a TTY. One workaround is to use a tool such as unbuffer or script to simulate a TTY.

Moreover, inasmuch as the use of a file at all is done as a workaround, I suggest using a FIFO to actually capture the line you want without needing to write to a file and poll that file's contents.

#!/bin/sh

newline='
'

# Let's define some helpers...
cleanup() {
  [ -e /proc/self/fd/3 ] && exec 3<&-                   ## close FD 3 if it's open
  rm -f "fifo.$$"                                       ## delete the FIFO from disk
  if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then  ## if our pid is still running...
    kill "$pid"                                         ## ...then shut it down.
  fi
}
die() { cleanup; echo "$*" >&2; exit 1; }

# Create a FIFO, and start `dns-sd` in the background *thinking* it's writing to a TTY
# but actually writing to that FIFO 
mkfifo "fifo.$$"
script -q -f -c 'dns-sd -lo -Z _mytest._tcp local' /proc/self/fd/1 |
  tr -d '\r' >"fifo.$$" & pid=$!

exec 3<"fifo.$$"

while read -t 1 -r line <&3; do
  case $line in
    "Script started on"*|";"*|"")  continue;;
    "Using "*|DATE:*|[[:digit:]]*) continue;;
    *)                             result="${result}${line}${newline}"; break
  esac
done

if [ -z "$result" ]; then
  die "Timeout before receiving a non-boilerplate line"
fi

printf '%s\n' "Retrieved a result:" "$result"
cleanup
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • If i run `script -q -f -c 'dns-sd -lo -Z _mytest._tcp local' yourfile` in foreground, stop the same command and check i see content in yourfile, however, If I run it in background. I see `yourfile` with NO content :( – ART Apr 25 '17 at 13:56
  • for second approach also i see following error `# ./test.sh Read result from FIFO: Using LocalOnly Read another line from FIFO: Script started on Tue Apr 25 09:57:00 2017 sh: can't kill pid 12254: No such process ` – ART Apr 25 '17 at 13:58
  • Re: #2, the only part of that that's an error is the process having exited, which doesn't actually *matter*. Keep reading -- that is to say, add another `read -t 1 -r line` until you actually get the content you're looking for. – Charles Duffy Apr 25 '17 at 14:42
  • *Sigh*. This would be rather considerably easier if I actually had a debugger on the system rather than needing to play telephone. Anyhow, happy with this as-amended? – Charles Duffy Apr 25 '17 at 14:47
  • yup! :) I will update If I find something easier. may be `unbuffer` or `stdbuf`. – ART Apr 25 '17 at 14:52
  • `unbuffer` would be my first stop, if you could afford the size of its dependency chain (being as it's part of `expect`, which requires TCL, and thus can be be pretty heavyweight on a storage-constrained embedded system). – Charles Duffy Apr 25 '17 at 14:52
  • we don't have `unbuffer`(i think its in core-utils) and `stdbuf` is also not present in busybox. So another ways would be to use C- API or Python API and implement same thing. – ART Apr 25 '17 at 15:02
  • No, `unbuffer` is not core-utils; it's part of `expect`. – Charles Duffy Apr 25 '17 at 15:02
  • oh okay..i see `expect` in build system. – ART Apr 25 '17 at 15:03
  • but, as I said above, its dependency chain is pretty huge and will increase the size of your system image substantially. – Charles Duffy Apr 25 '17 at 15:04
  • BTW, if you were going to use C or Python, I'd use them to directly run your DNS-SD lookup, not to build your own `unbuffer`. – Charles Duffy Apr 25 '17 at 15:05
  • hmm. That's what I am thinking of doing. As you said unbuffer is not wise choice for Embedded. – ART Apr 25 '17 at 15:06
  • 1
    Since the edited question makes it clear you want more than one line of output, I've amended appropriately. (Would have been ideal if that had been present initially, of course). – Charles Duffy Apr 25 '17 at 16:12