Como criar um aplicativo OSX para encerrar uma chamada para um script de shell?


10

Meu objetivo é incluir em um arquivo zip o que equivale a um atalho, em vez de dizer ao (s) cliente (s) para abrir o Terminal e executar um script de shell.

Meu implantável se parece basicamente com isso:

$ unzip Deliverable.zip 
$ cd Deliverable; ls
app.jar run.sh

Script em run.sh:

#!/bin/sh
java -jar app.jar

Há muito mais no diretório; basta dizer que preciso executar o script a partir do diretório Deliverable, pois preciso acessar os caminhos relativos a ele. No entanto, não posso garantir onde um cliente abrirá Deliverable.zip(pode ser o diretório inicial, o diretório Downloads, etc.)

Descobri isso que descreve como criar um novo fluxo de trabalho no Automator e salvá-lo como um aplicativo para iniciar um script de shell. Eu tentei fazer isso para embrulhar, run.shmas ele diz que não pode encontrar run.sh.

Alguém sugeriu que eu use o AppleScript e também me enviou um link para como usar o AppleScript para alternar para o diretório atual; há uma "ação" do manuscrito no automator; então criei um novo fluxo de trabalho e o salvei como um aplicativo. É assim que se parece:

o programa AppleScript Automator

O código:

on run {input, parameters}
    tell application "Finder"
        set current_path to container of (path to me) as alias
    end tell

    do shell script "java -jar app.jar" 

    return input
end run

E este é o erro que recebo ao executá-lo:

bem vindo a 2015

Vamos lá, isso deve ser bem simples. O que estou fazendo de errado aqui?


Bem, eu acabei de publicar uma atualização com um AppleScript mais simples, mas veja que fui derrotado com uma resposta que deveria funcionar melhor para você por grgarside. :-)
markhunte

O título desta pergunta não representa a questão real, então votei para baixo. A questão é mais estreita: trata-se de resolver um problema com a mensagem de erro "Os aplicativos PowerPC não são mais suportados" e é isso que deve estar no título da pergunta. Na verdade, estou procurando a resposta para como criar um pacote de aplicativos. O OP sabe como criar um pacote configurável, mas encontrou um erro.
Jason

Respostas:


4

Renomeie o arquivo .sh para .command e você pode fazer o cd no diretório em que o arquivo .command está localizado, com o seguinte no início do arquivo:

cd "$(dirname $BASH_SOURCE)"

7

Eu posso ver algumas coisas erradas lá.

Primeiro, você abriu um fluxo de trabalho e não um Aplicativo.

Você deve escolher Aplicativo ao fazer sua seleção para o tipo de arquivo do Automator.

insira a descrição da imagem aqui

E o código que você possui não funcionará conforme o esperado, pois você não alterou o diretório. (CD).

No código que você possui, tudo o que está fazendo é obter o caminho como um alias e armazená-lo na variável current_path e em um formato inadequado para os comandos unix.

Mas você não usa.

Portanto, o diretório atual provavelmente será sua pasta pessoal

Nesta fase, não há como dizer o que está tentando lançar.

Se eu executá-lo como você, eu entendo.

insira a descrição da imagem aqui

O que faz sentido, pois não tenho o Java instalado. Mas, se o fizesse, não esperaria encontrar o arquivo certo.

O Applescript precisa ter esta aparência.

on run {input, parameters}
    tell application "Finder"
        set current_path to container of (path to me) as alias
    end tell

    do shell script "cd " & quoted form of (POSIX path of current_path) & " ;ls | open -fe"

    return input
end run 

No meu exemplo

do shell script "cd " & quoted form of (POSIX path of current_path) & " ;/bin/ls | /usr/bin/open -fe"

Eu cd para o caminho POSIX do alias na variável current_path

ou seja, do "alias" Macintosh HD: Aplicativos: "" para "/ Aplicativos /"

O quoted form of escape do caminho usando aspas.

Eu usei o comando / bin / ls e canalize-o para abrir no TextEdit stdin como uma demonstração aqui, para que você possa testar para ver se está chegando à área que espera.

Você usaria algo como;

do shell script "cd " & quoted form of (POSIX path of current_path) & " ;\"java -jar app.jar\""

atualizar:

Uma outra maneira é apenas usar Applescript puro.

on run {input, parameters}
    tell application "Finder"
        set current_path to container of (path to me)

        set theFile to (current_path) as alias

        open file "java -jar app.jar" of theFile
    end tell


end run

Isso está muito próximo de uma solução; Confirmo que o ls | opencódigo definitivamente abre o diretório que eu quero, o que é ótimo. Mas quando ligo para abrir Client.app, recebo: LSOpenURLsWithRole() failed with error -10665 for the file <path-to-Client.app> - algumas pesquisas sobre o que esse erro significa sugeriram um problema de permissão, verifiquei e os +xsinalizadores foram definidos. Eu também tentei isso , e isso não funcionou (com o mesmo erro).
emptyset

Observe que a abertura Client.appdo Finder (clique duplo) também resulta no mesmo pop-up de erro do PowerPC.
emptyset

@emptyset I call open Client.appEste é o aplicativo Automator. Pelo que eu entendo no automator você tem o código applescript: do shell script "cd " & quoted form of (POSIX path of current_path) & " ;\"java -jar app.jar\"". Então, onde você está usando o opencomando? que, pelo que entendi, você não precisa usá-lo. Os clientes estarão usando duplo clique no aplicativo e o aplicativo irá executar o java
markhunte

Eu testei de duas maneiras: na linha de comando: $ open Client.appe clicando duas vezes. Sua versão com a invocação ls | open -fefunciona, mas quando eu a altero java -jar app.jar, está me dando esse erro.
emptyset

@emptyset trydo shell script "cd " & quoted form of (POSIX path of current_path) & " ; " & quoted form of "java -jar app.jar"
markhunte

6

Caminho para o Script

No AppleScript, você precisa alterar o diretório de trabalho atual (cwd) antes de emitir o comando java. Faça isso com uma linha AppleScript como:

do shell script "cd " & quoted form of (POSIX path of file_path) & " && java -jar app.jar"

O &&é importante. Se cdfor bem - sucedido, o javacomando será iniciado dentro do cwd certo . Se cdfalhar, o javacomando não será executado.

Os problemas que você provavelmente encontrará incluem:

  • escapar do caminho POSIX passado para cd; os usuários terão pastas e espaços com nomes estranhos em seus caminhos.
  • o cdpode falhar; envolva seu AppleScript em um bloco try para detectar alguns erros e avisar o usuário.

perl

Pessoalmente, eu usaria um script perl curto no lugar de um script bash.

#!/usr/bin/env perl

use strict;
use warnings;
use FindBin qw($Bin); # $Bin is a path to the script's parent folder

`cd "$Bin" && java -jar app.jar`;

Existem maneiras muito melhores de escrever esse fragmento de perl, mas isso deve funcionar.

Aplicativo Automator

A melhor abordagem é solucionar os problemas da abordagem do Automator. A resposta de @ markhunte discute como corrigir o caminho e criar um aplicativo . Isso deve levá-lo a maior parte do caminho.

Consulte também o caminho AppleScript relativo ao local do script .

appify - crie o aplicativo Mac mais simples possível a partir de um shell script

Como alternativa, você pode usar o script appify de Thomas Aylott para agrupar seu script shell em um aplicativo OS X. O artigo de Mathias Bynen mostra como usar o script, como criar aplicativos simples para Mac a partir de shell scripts .

#!/bin/bash

if [ "$1" = "-h" -o "$1" = "--help" -o -z "$1" ]; then cat <<EOF
appify v3.0.1 for Mac OS X - http://mths.be/appify
Creates the simplest possible Mac app from a shell script.
Appify takes a shell script as its first argument:
    `basename "$0"` my-script.sh
Note that you cannot rename appified apps. If you want to give your app
a custom name, use the second argument:
    `basename "$0"` my-script.sh "My App"
Copyright (c) Thomas Aylott <http://subtlegradient.com/>
Modified by Mathias Bynens <http://mathiasbynens.be/>
EOF
exit; fi

APPNAME=${2:-$(basename "$1" ".sh")}
DIR="$APPNAME.app/Contents/MacOS"

if [ -a "$APPNAME.app" ]; then
    echo "$PWD/$APPNAME.app already exists :("
    exit 1
fi

mkdir -p "$DIR"
cp "$1" "$DIR/$APPNAME"
chmod +x "$DIR/$APPNAME"

echo "$PWD/$APPNAME.app"

As melhorias contribuídas pela comunidade para este script estão disponíveis:

Assinatura de código

Depois de criar seu pacote de aplicativos, ele deverá ser assinado por código. Um aplicativo com código assinado será iniciado sem exigir que seus clientes desabilitem o Gatekeeper.

Código assine seu aplicativo usando seu Apple Developer ID e o codesigncomando:

codesign -s <identity> -v <code-path> 

A assinatura de código é uma tecnologia de segurança usada no OS X que permite certificar que um aplicativo foi criado por você. Depois que um aplicativo é assinado, o sistema pode detectar qualquer alteração no aplicativo, seja ela introduzida acidentalmente ou por código malicioso.

Saiba mais sobre assinatura de código no site Apple Developer.


Obrigado pela dica sobre assinatura de código; Estou analisando isso agora e testando o script appify!
emptyset

script appify não funcionou; problema no mesmo caminho
emptyset

@emptyset Adicionei uma seção de caminho e perl. Também pode valer a pena separar o problema do caminho em uma nova pergunta. Se você pode corrigir isso, pode usar o Automator ou o script appify.
Graham Miln

5

Use Platypus : "Platypus é uma ferramenta de desenvolvedor do OS X que cria aplicativos Mac nativos a partir de scripts interpretados ..."

Platypus é uma ferramenta de desenvolvedor do OS X que cria aplicativos Mac nativos a partir de scripts interpretados


4

Você pode mudar run.shpara run.commando usuário e clicar duas vezes nele?


Isso quase funcionou! No entanto, ele executou o arquivo no contexto do diretório inicial do usuário ( cd ~), o que causou uma falha.
emptyset

1
@emptyset Use $ BASH_SOURCE, consulte apple.stackexchange.com/a/201482
grg

1

Aqui está a minha opinião sobre o que eu entendi que você está tentando realizar. O código é muito longo de propósito.

Tudo o que você precisa fazer é copiar o código no Editor de maçãs, fazer as alterações desejadas e salvá-lo como um aplicativo.

Quanto ao diálogo sobre o aplicativo PowerPC não suportado, eu não sei. Você pode executá-lo na linha de comando? Gostaria de verificar se para confirmar se o aplicativo funciona primeiro.

#
# STEP 1: locate and confirm zip file exists
#
#   This is long winded on purpose. It is meant to save the user some scrolling and 
#   and a click... Isn't this what computers are for to save time? :)
#

# Zip file name 
set zipname to "Deliverable.zip"

# Locate the zip file
set zippath to POSIX path of (choose folder)
log zippath
set qzippath to quoted form of zippath
log qzippath
set zipfile to (zippath & zipname)
set qzipfile to quoted form of (zippath & zipname)
log qzipfile

# Check for the file... Use either test not both :)
try
    # using shell test - case sensetive
    do shell script "test -f " & qzipfile

    # using native test - doesn't like quoted forms and case insensetive...
    POSIX file zipfile as alias
on error
    display dialog "ERROR: Zip file was not found at selected folder." as text ¬
        buttons {"OK"} with icon caution ¬
        with title "Alert"
    return
end try


#
# STEP 2: Zip found. Unzip it
#
try
    # Add " -d Deliverable" at the end to force directory  
    # unzip -o to force overwrite for testing....
    do shell script "cd " & qzippath & "; unzip -o " & zipname
on error eStr
    display dialog "ERROR: Failed to unzip file. Message returned was, " & ¬
        return & return & eStr as text ¬
        buttons {"OK"} with icon caution ¬
        with title "Unzip Error"
    return
end try


#
# STEP 3: Run script 
#
set dpath to (zippath & "Deliverable/")
log dpath
set qdpath to quoted form of dpath
log qdpath
try
    do shell script "cd " & qdpath & ";  sh ./run.sh"
on error eStr
    display dialog "ERROR: Failed to launch script. Message returned was, " & ¬
        return & return & eStr as text ¬
        buttons {"OK"} with icon caution ¬
        with title "Deliverable Script Launch"
    return
end try
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.