Why xargs can't work with tail -f?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












2














I want tail -f /var/log/syslog | grep it with pattern "arpwatch" and send every line to myself via jabber: xmpp username@jabber.server using xargs



tail -f /var/log/syslog | grep arpwatch | xargs sendxmpp username@jabber.server


no working.



but tail /var/log/syslog | grep arpwatch | sendxmpp username@jabber.server



works well.



I think it's some fundamental thing about xargs and tail -f that I don't understand.










share|improve this question























  • Related: superuser.com/questions/1038841/…
    – RoVo
    Dec 19 '18 at 14:16















2














I want tail -f /var/log/syslog | grep it with pattern "arpwatch" and send every line to myself via jabber: xmpp username@jabber.server using xargs



tail -f /var/log/syslog | grep arpwatch | xargs sendxmpp username@jabber.server


no working.



but tail /var/log/syslog | grep arpwatch | sendxmpp username@jabber.server



works well.



I think it's some fundamental thing about xargs and tail -f that I don't understand.










share|improve this question























  • Related: superuser.com/questions/1038841/…
    – RoVo
    Dec 19 '18 at 14:16













2












2








2







I want tail -f /var/log/syslog | grep it with pattern "arpwatch" and send every line to myself via jabber: xmpp username@jabber.server using xargs



tail -f /var/log/syslog | grep arpwatch | xargs sendxmpp username@jabber.server


no working.



but tail /var/log/syslog | grep arpwatch | sendxmpp username@jabber.server



works well.



I think it's some fundamental thing about xargs and tail -f that I don't understand.










share|improve this question















I want tail -f /var/log/syslog | grep it with pattern "arpwatch" and send every line to myself via jabber: xmpp username@jabber.server using xargs



tail -f /var/log/syslog | grep arpwatch | xargs sendxmpp username@jabber.server


no working.



but tail /var/log/syslog | grep arpwatch | sendxmpp username@jabber.server



works well.



I think it's some fundamental thing about xargs and tail -f that I don't understand.







xargs tail






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 19 '18 at 20:54









Rui F Ribeiro

39k1479129




39k1479129










asked Dec 19 '18 at 14:08









StayCool

141




141











  • Related: superuser.com/questions/1038841/…
    – RoVo
    Dec 19 '18 at 14:16
















  • Related: superuser.com/questions/1038841/…
    – RoVo
    Dec 19 '18 at 14:16















Related: superuser.com/questions/1038841/…
– RoVo
Dec 19 '18 at 14:16




Related: superuser.com/questions/1038841/…
– RoVo
Dec 19 '18 at 14:16










2 Answers
2






active

oldest

votes


















2














xargs command tries to collect as many input items (lines, words) as it can to one invocation of the command, and it doesn't particularly care about the timing of the input data. If the tail process is killed, or xargss buffer get filled, it will run command with the arguments it received by then. However, tail -f usually doesn't finish by itself, and the limit for command line arguments can be large, so it seems like it doesn't work at all.



You could use xargs -n1 to have it pass only one input item at a time to command, but you'll be hit by the fact that xargs uses whitespace to split the input into items, so an input line of foo bar would cause the command to run twice.



With GNU xargs, xargs -n1 -d 'n' should do what you want: run command once for each input line, with the full line passed as a single argument.



Try, e.g. with and without the -d and -n and make note of the output timing:



$ ( echo "123 456"; sleep 1; echo foo; sleep 1; echo doo ) | xargs -d 'n' -n1 printf ':%sn'


xargs -L 1 would also work, but it will still split the line to separate arguments, instead of passing the whole line as one argument.






share|improve this answer






























    1














    grep has the option --line-buffered to output each line immediately instead of waiting for more input.



    For xargs, as suggested by @ikkachu, you need to separate by newlines instead of spaces. You can use xargs -L for that.



    This should work:



    tail -f /var/log/syslog 
    | grep --line-buffered arpwatch
    | xargs -L1 sendxmpp username@jabber.server





    share|improve this answer






















    • -L1 is not to separate by newline, but to run one command per line with as many words as there are on the line as separate arguments; IOW, space, tab (and other whitespace depending on the implementation) and quotes/blackslash are still used as delimiters. To split by newline, you need either GNU's -d 'n' or escape all other blanks and quoting operators supported by xargs. Or with some implementations that suport -0 and not -d, use tr 'n' '' in combination with xargs -0.
      – Stéphane Chazelas
      Dec 19 '18 at 14:50











    Your Answer








    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "106"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f489926%2fwhy-xargs-cant-work-with-tail-f%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    xargs command tries to collect as many input items (lines, words) as it can to one invocation of the command, and it doesn't particularly care about the timing of the input data. If the tail process is killed, or xargss buffer get filled, it will run command with the arguments it received by then. However, tail -f usually doesn't finish by itself, and the limit for command line arguments can be large, so it seems like it doesn't work at all.



    You could use xargs -n1 to have it pass only one input item at a time to command, but you'll be hit by the fact that xargs uses whitespace to split the input into items, so an input line of foo bar would cause the command to run twice.



    With GNU xargs, xargs -n1 -d 'n' should do what you want: run command once for each input line, with the full line passed as a single argument.



    Try, e.g. with and without the -d and -n and make note of the output timing:



    $ ( echo "123 456"; sleep 1; echo foo; sleep 1; echo doo ) | xargs -d 'n' -n1 printf ':%sn'


    xargs -L 1 would also work, but it will still split the line to separate arguments, instead of passing the whole line as one argument.






    share|improve this answer



























      2














      xargs command tries to collect as many input items (lines, words) as it can to one invocation of the command, and it doesn't particularly care about the timing of the input data. If the tail process is killed, or xargss buffer get filled, it will run command with the arguments it received by then. However, tail -f usually doesn't finish by itself, and the limit for command line arguments can be large, so it seems like it doesn't work at all.



      You could use xargs -n1 to have it pass only one input item at a time to command, but you'll be hit by the fact that xargs uses whitespace to split the input into items, so an input line of foo bar would cause the command to run twice.



      With GNU xargs, xargs -n1 -d 'n' should do what you want: run command once for each input line, with the full line passed as a single argument.



      Try, e.g. with and without the -d and -n and make note of the output timing:



      $ ( echo "123 456"; sleep 1; echo foo; sleep 1; echo doo ) | xargs -d 'n' -n1 printf ':%sn'


      xargs -L 1 would also work, but it will still split the line to separate arguments, instead of passing the whole line as one argument.






      share|improve this answer

























        2












        2








        2






        xargs command tries to collect as many input items (lines, words) as it can to one invocation of the command, and it doesn't particularly care about the timing of the input data. If the tail process is killed, or xargss buffer get filled, it will run command with the arguments it received by then. However, tail -f usually doesn't finish by itself, and the limit for command line arguments can be large, so it seems like it doesn't work at all.



        You could use xargs -n1 to have it pass only one input item at a time to command, but you'll be hit by the fact that xargs uses whitespace to split the input into items, so an input line of foo bar would cause the command to run twice.



        With GNU xargs, xargs -n1 -d 'n' should do what you want: run command once for each input line, with the full line passed as a single argument.



        Try, e.g. with and without the -d and -n and make note of the output timing:



        $ ( echo "123 456"; sleep 1; echo foo; sleep 1; echo doo ) | xargs -d 'n' -n1 printf ':%sn'


        xargs -L 1 would also work, but it will still split the line to separate arguments, instead of passing the whole line as one argument.






        share|improve this answer














        xargs command tries to collect as many input items (lines, words) as it can to one invocation of the command, and it doesn't particularly care about the timing of the input data. If the tail process is killed, or xargss buffer get filled, it will run command with the arguments it received by then. However, tail -f usually doesn't finish by itself, and the limit for command line arguments can be large, so it seems like it doesn't work at all.



        You could use xargs -n1 to have it pass only one input item at a time to command, but you'll be hit by the fact that xargs uses whitespace to split the input into items, so an input line of foo bar would cause the command to run twice.



        With GNU xargs, xargs -n1 -d 'n' should do what you want: run command once for each input line, with the full line passed as a single argument.



        Try, e.g. with and without the -d and -n and make note of the output timing:



        $ ( echo "123 456"; sleep 1; echo foo; sleep 1; echo doo ) | xargs -d 'n' -n1 printf ':%sn'


        xargs -L 1 would also work, but it will still split the line to separate arguments, instead of passing the whole line as one argument.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Dec 19 '18 at 14:42

























        answered Dec 19 '18 at 14:20









        ilkkachu

        55.9k784155




        55.9k784155























            1














            grep has the option --line-buffered to output each line immediately instead of waiting for more input.



            For xargs, as suggested by @ikkachu, you need to separate by newlines instead of spaces. You can use xargs -L for that.



            This should work:



            tail -f /var/log/syslog 
            | grep --line-buffered arpwatch
            | xargs -L1 sendxmpp username@jabber.server





            share|improve this answer






















            • -L1 is not to separate by newline, but to run one command per line with as many words as there are on the line as separate arguments; IOW, space, tab (and other whitespace depending on the implementation) and quotes/blackslash are still used as delimiters. To split by newline, you need either GNU's -d 'n' or escape all other blanks and quoting operators supported by xargs. Or with some implementations that suport -0 and not -d, use tr 'n' '' in combination with xargs -0.
              – Stéphane Chazelas
              Dec 19 '18 at 14:50
















            1














            grep has the option --line-buffered to output each line immediately instead of waiting for more input.



            For xargs, as suggested by @ikkachu, you need to separate by newlines instead of spaces. You can use xargs -L for that.



            This should work:



            tail -f /var/log/syslog 
            | grep --line-buffered arpwatch
            | xargs -L1 sendxmpp username@jabber.server





            share|improve this answer






















            • -L1 is not to separate by newline, but to run one command per line with as many words as there are on the line as separate arguments; IOW, space, tab (and other whitespace depending on the implementation) and quotes/blackslash are still used as delimiters. To split by newline, you need either GNU's -d 'n' or escape all other blanks and quoting operators supported by xargs. Or with some implementations that suport -0 and not -d, use tr 'n' '' in combination with xargs -0.
              – Stéphane Chazelas
              Dec 19 '18 at 14:50














            1












            1








            1






            grep has the option --line-buffered to output each line immediately instead of waiting for more input.



            For xargs, as suggested by @ikkachu, you need to separate by newlines instead of spaces. You can use xargs -L for that.



            This should work:



            tail -f /var/log/syslog 
            | grep --line-buffered arpwatch
            | xargs -L1 sendxmpp username@jabber.server





            share|improve this answer














            grep has the option --line-buffered to output each line immediately instead of waiting for more input.



            For xargs, as suggested by @ikkachu, you need to separate by newlines instead of spaces. You can use xargs -L for that.



            This should work:



            tail -f /var/log/syslog 
            | grep --line-buffered arpwatch
            | xargs -L1 sendxmpp username@jabber.server






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 19 '18 at 14:35

























            answered Dec 19 '18 at 14:29









            RoVo

            2,568215




            2,568215











            • -L1 is not to separate by newline, but to run one command per line with as many words as there are on the line as separate arguments; IOW, space, tab (and other whitespace depending on the implementation) and quotes/blackslash are still used as delimiters. To split by newline, you need either GNU's -d 'n' or escape all other blanks and quoting operators supported by xargs. Or with some implementations that suport -0 and not -d, use tr 'n' '' in combination with xargs -0.
              – Stéphane Chazelas
              Dec 19 '18 at 14:50

















            • -L1 is not to separate by newline, but to run one command per line with as many words as there are on the line as separate arguments; IOW, space, tab (and other whitespace depending on the implementation) and quotes/blackslash are still used as delimiters. To split by newline, you need either GNU's -d 'n' or escape all other blanks and quoting operators supported by xargs. Or with some implementations that suport -0 and not -d, use tr 'n' '' in combination with xargs -0.
              – Stéphane Chazelas
              Dec 19 '18 at 14:50
















            -L1 is not to separate by newline, but to run one command per line with as many words as there are on the line as separate arguments; IOW, space, tab (and other whitespace depending on the implementation) and quotes/blackslash are still used as delimiters. To split by newline, you need either GNU's -d 'n' or escape all other blanks and quoting operators supported by xargs. Or with some implementations that suport -0 and not -d, use tr 'n' '' in combination with xargs -0.
            – Stéphane Chazelas
            Dec 19 '18 at 14:50





            -L1 is not to separate by newline, but to run one command per line with as many words as there are on the line as separate arguments; IOW, space, tab (and other whitespace depending on the implementation) and quotes/blackslash are still used as delimiters. To split by newline, you need either GNU's -d 'n' or escape all other blanks and quoting operators supported by xargs. Or with some implementations that suport -0 and not -d, use tr 'n' '' in combination with xargs -0.
            – Stéphane Chazelas
            Dec 19 '18 at 14:50


















            draft saved

            draft discarded
















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f489926%2fwhy-xargs-cant-work-with-tail-f%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown






            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay